java中的套接字初探

TCP和UDP

TCP和UDP他们在OSI分层中都位于传输层,为应用层提供支持。TCP属于面向连接的网络传输协议,客户端和服务器端需要建立稳定的连接,才能相互传输数据。而UDP是面向无连接的网络传输协议,客户端和服务器端不需要建立连接,客户端发送出去的数据包不管对方是否存在,都可以发送。

TCP

TCPTransmission Control Protocol)传输控制协议属于一种稳定可靠的连接方式,客户端与服务器在建立连接之前需要进行三次握手。连接虽然稳定,但是由于数据传输过程复杂,导致传输效率较UDP低很多。通常运用在数据要求准确的场景下,如文件传输、网页显示、邮件传递等等。在javaTCP通过Socket和ServerSocket两个类来实现TCP的功能。

1.TCP客户端Socket
//客户端类
public class TestSocketclient {
	//构造方法
	public TestSocketclient(String ip,int port){
		try {
			@SuppressWarnings("resource")
			Socket socket = new Socket(ip,port);//指明服务器ip和端口号
			//向服务器发送消息
			String data = "hello server";
			OutputStream os = socket.getOutputStream();//输出流就是向服务器发送数据的流
			os.write(data.getBytes());
			
			//接收来自服务器的消息
			InputStream is = socket.getInputStream();//输入流就是接收来自服务器数据的流
			byte[] serverinfo = new byte[1024];
			int n = -1;
			while((n=is.read(serverinfo))!=-1){
				String string = new String(serverinfo,0,n);
				System.out.println(string);
			}
			
			os.close();
			is.close();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//启动方法,应该让服务器端先启动
	public static void main(String[] args) {
		try {
			new TestSocketclient(InetAddress.getLocalHost().getHostAddress(),8888);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
	}
}
2.TCP服务端ServerSocket
//服务器端
public class TestServerSocket {
	//构造方法
	public TestServerSocket(int port){
		try {
			ServerSocket ss = new ServerSocket(port);//监听端口
			//接收来自客户端的数据,该方法accept()是阻塞方法,直到接到请求才往下执行。
			Socket accept = ss.accept();
			InputStream is = accept.getInputStream();
			byte[] packet = new byte[1024];
			int n = is.read(packet);
			String string = new String(packet,0,n);
			System.out.println(string);
			//向客户端发送消息
			OutputStream os = accept.getOutputStream();
			os.write("hello client".getBytes());
			
			os.close();
			is.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	//启动方法
	public static void main(String[] args) {
		new TestServerSocket(8888);
	}
}

UDP

UDPUser Datagram Protocol)用户数据报协议属于一种不太稳定的数据传输协议,往往在传输过程中容易丢失数据报,但不会丢失太多,不影响总体数据的完整性。看上去UDP既然不稳定,还丢失数据,为什么还保留至今,没有被摒弃?那是因为它具有非常不凡的传输效率。应用也非常广泛,如网络游戏,虽不是所有数据都是UDP(如玩家属性)但其分量占比很大、QQ聊天工具、实时视频通话、视频会议等等。在java中使用DatagramSocket类实现UDP功能。

1.UDP客户端
//客户端
public class TestUDPclient {
	//构造方法
	public TestUDPclient(String ip,int port){
		
		try {
			//客户端不用在socket上指明ip和port
			DatagramSocket ds = new DatagramSocket();
			
			byte[] buf = "nihao 服务器".getBytes();
			int length = buf.length-4;//必须是绑定数据的大小,不能大于,可以小于,不能为负
			InetAddress address = InetAddress.getByName(ip);
			//在数据报上指明服务器的ip和port
			DatagramPacket dp = new DatagramPacket(buf,length, address, port);
			//发送数据
			ds.send(dp);
			//关闭套接字
			ds.close();
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//启动方法
	public static void main(String[] args) {
		new TestUDPclient("localhost",7777);
	}
}
2.UDP服务器端
//服务器端
public class TestUDPServer {
	//构造方法
	public TestUDPServer(int port){
		try {
			
			DatagramSocket ps = new DatagramSocket(port);//监听port端口是否有请求
			byte[] b= new byte[1024];
			DatagramPacket pd = new DatagramPacket(b, 1024);//准备一个空包接收数据用
			//接收数据
			ps.receive(pd);
			//得到数据并打印
			byte[] data = pd.getData();
			System.out.println(new String(data,0,data.length));
			//关闭套接字
			ps.close();
		} catch (Exception e) {
		}
	}
	//启动方法
	public static void main(String[] args) {
		new TestUDPServer(7777);
	}

}
3.补充

UDP在用DatagramSocket类实现时客户端和服务器端都是使用相同的类,他们是通过是否配置了端口号和IP来区分服务器和客户端的。只要配置了端口和IP的DatagramSocket都可以充当服务器端。但是同一IP地址下端口号不能一样,不然会报端口占用的异常。谁先接收数据谁先启动,以下是举例说明:

  • 客户端
public class TestUDPclient {
	
	public TestUDPclient(String ip,int port){
		
		try {
			//作为端口号为8888的服务器端
			DatagramSocket ds = new DatagramSocket(8888);
			
			byte[] buf = "nihao 服务器".getBytes();
			int length = buf.length;
			InetAddress address = InetAddress.getByName(ip);
			DatagramPacket dp = new DatagramPacket(buf,length, address, port);
			
			ds.send(dp);
			//发送后再来接收数据
			DatagramPacket dp2 = new DatagramPacket(new byte[1024], 1024);
			ds.receive(dp2);
			byte[] data = dp2.getData();
			System.out.println(new String(data,0,data.length));
			
			ds.close();
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		new TestUDPclient("localhost",7777);
	}
}
  • 服务器端
public class TestUDPServer {
	
	public TestUDPServer(int port){
		try {
			//作为端口号为7777的服务器端
			DatagramSocket ps = new DatagramSocket(port);
			byte[] b= new byte[1024];
			DatagramPacket pd = new DatagramPacket(b, 1024);
			
			ps.receive(pd);
			
			byte[] data = pd.getData();
			System.out.println(new String(data,0,data.length));
			//接收完数据再发送,发送给本地端口号为8888的服务器端
			DatagramPacket dp2 = new DatagramPacket("nihao".getBytes(),5,InetAddress.getByName("localhost"),8888);
			ps.send(dp2);
			
			ps.close();
		} catch (Exception e) {
		}
	}
	
	public static void main(String[] args) {
		new TestUDPServer(7777);
	}

}
发布了6 篇原创文章 · 获赞 2 · 访问量 510

猜你喜欢

转载自blog.csdn.net/wl12346/article/details/104840355