初学socket编程(网络编程)

socket编程可以理解为是一种二进制+IP+端口的一种通讯模式,在任何语言中,都有socket编程,因此几乎所有语言的socket都可以互通。只要是涉及到通讯方面的如QQ,微信等都是涉及到socket,只是他们自己进行了封装。socket的本质是对tcp/ip的封装。

网络通讯:

UDP:是面向无连接的,所以效率较高,不会建立连接,不安全。不管有没有接收方,只管向指定地址发送东西。(但要求大小在64k以内)底层使用UDP协议。

TCP:是面向连接的,三次握手成功之后才能通讯,字节流传输,效率低于UDP,但是安全性高(因为采用了三次握手和四次挥手协议)。双方需要建立连接才能通讯(发送数据)。底层使用TCP协议,TCP底层是用HTTP协议。

TCP三次握手四次挥手示意图:

TCP通讯实现:

先创建服务器端:

//TCP协议服务端
public class Server {

	public static void main(String[] args) throws IOException {
		System.out.println("TCP服务端启动了");
		//启动服务端
		ServerSocket serverSocket = new ServerSocket(8080);//传入端口号
		//等待客户端连接(如果客户端不连接进来,程序一直阻塞在这里等待)
		Socket accept = serverSocket.accept();
		//模拟客户端给服务端发送消息的场景
		//生成输入流
		InputStream is = accept.getInputStream();
		//定义字节
		byte [] bytes = new byte[1024];
		//读取
		int length = is.read(bytes);
		//将byte数组转为String
		String result = new String(bytes, 0, length);
		System.out.println("服务器端已经接收到客户端发送的消息:"+result);
	}
}

TCP客户端:

//TCP客户端
public class TCPClient {

	public static void main(String[] args) throws Exception, IOException {
		//创建socket
		Socket socket = new Socket("127.0.0.1", 8080);//传入IP和端口号
		//创建输出流
		OutputStream os = socket.getOutputStream();
		//先定义一段话
		String mes = "hello";
		//发送
		os.write(mes.getBytes());
		System.out.println("客户端发送消息完毕");
		
	}
}

先运行服务器端:

运行客户端:

消息发送完成后,我们再看服务端打印的内容:

下面我们继续写一下服务器接收到消息后的反馈,服务器端:

//TCP协议服务端
public class Server {

	public static void main(String[] args) throws IOException {
		//启动服务端
		ServerSocket serverSocket = new ServerSocket(8080);
		try {
			System.out.println("TCP服务端启动了");
			//等待客户端连接(如果客户端不连接进来,程序一直阻塞在这里等待)
			Socket accept = serverSocket.accept();
			//模拟客户端给服务端发送消息的场景
			//生成输入流
			InputStream is = accept.getInputStream();
			//定义字节
			byte [] bytes = new byte[1024];
			//读取
			int length = is.read(bytes);
			//将byte数组转为String
			String result = new String(bytes, 0, length);
			System.out.println("服务器端已经接收到客户端发送的消息:"+result);
			
			//返回消息
			//得到一个OutputStream 
			OutputStream outputStream = accept.getOutputStream();
			//将输出流转为打印流
			PrintWriter pw = new PrintWriter(outputStream);
			pw.print("我是服务器,已经收到消息");
			pw.flush();
			accept.shutdownOutput();
		} catch (Exception e) {
			// TODO: handle exception
		}finally {
			//使用try,万一代码出现异常,我们就在finally中关闭连接
			serverSocket.close();
		}
		
	}
}

客户端:

//TCP客户端
public class TCPClient {

	public static void main(String[] args) throws Exception, IOException {
		//创建socket
		Socket socket = new Socket("127.0.0.1", 8080);//传入IP和端口号
		try {
			//创建输出流
			OutputStream os = socket.getOutputStream();
			//先定义一段话
			String mes = "hello";
			//发送
			os.write(mes.getBytes());
			System.out.println("客户端发送消息完毕");
			//获取服务端发送的消息
			//获取InputStream
			InputStream is = socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			//读
			String result = br.readLine();
			System.out.println("客户端===》》服务器返回的结果:"+result);
		} catch (Exception e) {
			
		}finally {
			socket.close();
		}
		
	}
}

先运行服务端:

再运行客户端:

此时再看服务端:

UDP实现:

先创建UDP服务端:

//UDP服务端
public class UdpServer {

	public static void main(String[] args) throws IOException {
		System.out.println("udp服务启动了");
		//定义DatagramSocket
		DatagramSocket ds = new DatagramSocket(8080);//不传地址,默认本级
		//创建接收的数组
		byte [] buf = new byte[1024];
		//获取客户端发送的数据
		DatagramPacket dp = new DatagramPacket(buf, buf.length);
		//直到有客户端连接起来,程序才会执行下去,否则一直阻塞在这里
		ds.receive(dp);
		String string = dp.getAddress().toString();
		String data = new String(dp.getData(),0,dp.getLength());
		System.out.println("服务器接收从IP:"+string+"传输的数据"+data);
	}
}

创建UDP客户端:

//udp客户端
public class UdpClient {

	public static void main(String[] args) throws IOException {
		DatagramSocket ds = new DatagramSocket();//此处不用传参数
		//定义发送的数据
		String mes = "hello";
		byte[] bytes = mes.getBytes();
		DatagramPacket dp = new DatagramPacket(bytes, bytes.length,new InetSocketAddress("127.0.0.1",8080));
		//发送数据
		ds.send(dp);
		ds.close();
		System.out.println("客户端发送信息完毕");
	}
}

先启动服务端:

再启动客户端:

再看服务端:

下面我们来验证一下UDP是无连接的,发送消息时不会关心服务端是否在。我们关掉服务端,启动客户端,此时不会出现异常错误,即验证上述。然后我们关掉服务端和客户端,再重新启动服务端和客户端时,刚才在服务端没有启动时发送的数据已经被覆盖掉了,所以服务端接收到的是它启动之后的数据。

猜你喜欢

转载自blog.csdn.net/QYHuiiQ/article/details/84443798