Java Socket通信

今天讲解的是JAVA中通常用的一种通信方法,通过一个双向的通信连接实现数据的交换,其中一端称为Socket。

基本原理为:
Socket socket=new Socket( 服务器,端 口)
输出流.write( 数据) 和 byte b=输入流 .read ()

在传送过程中,数据像包裹意向被层层通信协议封装起来,最常见的就是TCP/IP 通信协议,在网络上传输时,首先包装为TCP格式,再包装为IP格式 。

Java聊天系统怎么做 java 聊天_System

因为Socket实现的是UDP传送,UDP 通信不用建立连结就可发送,只负责发送,不保证接收的有效性,所以在进行大量数据流传送时可能会出现丢包现象。

通信分为客户端和服务端,可利用如下代码实现简单的 UDP 客户机和服务间通信

发送端
//UDP发送端:一台机器可能有多个IP地址,
//把数据以本机192.168.1.147地址上13000号端号,发送到192.168.1.149上的14000端口
//1.创建要用来发送的本地地址
SocketAddress localAddr = new InetSocketAddress("192.168.1.147", 13000);
//2.创建发送的Socket对象
DatagramSocket dSender = new DatagramSocket(localAddr);
int count=0;
while(true){
count++;
byte buffer[] = (count+"-hello").getBytes();//3.要发送的数据
//4.发送数据的目标地址和端口
SocketAddress destAdd = new InetSocketAddress("192.168.1.149", 14000);
//5.创建要发送的数据包,指定内容,指定目标地址
DatagramPacket dp = new DatagramPacket(buffer, buffer.length, destAdd);
dSender.send(dp);//6.发送
System.out.println("数据已发送: "+count);
Thread.sleep(1000);
}//end while
接收端
//1.接收端:在本机接收的机址和等待的端口号
SocketAddress localAddr = new InetSocketAddress("192.168.1.149", 14000);
//2.接收的服务器UDP端口
DatagramSocket recvSocket = new DatagramSocket(localAddr);
while(true){
byte[] buffer = new byte[20]; //3.指定接收缓冲区大小:每个包20字节
//4.创建接收数据包对象
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
//5.阻塞等待数据到来,如果收到数据,存入packet中的缓冲区中
System.out.println("UDP服务器等待接收数据:");
recvSocket.receive(packet); //6.在此等待接收对方发的UDP包
//得到发送方的IP和端口
SocketAddress address = packet.getSocketAddress();
//转换接收到的数据为字符串
String msg=new String(packet.getData()).trim();
//接收到后,打印出收到的数据长度
System.out.println("recv is:"+msg+" from:"+address);
}

在此我设置了一个聊天页面,同时承担发送和接收任务,放入程序中运行的完整代码为

//主函数
public class Client1Message {
	public static void main(String[] args){
		Client1Message me = new Client1Message();
		me.initUI();
	}
	public void initUI(){
		JFrame jf = new JFrame();
		jf.setSize(300,350);
		jf.setTitle("Message-Client1");
		jf.setDefaultCloseOperation(3);
		java.awt.FlowLayout flow = new java.awt.FlowLayout();
		jf.setLayout(flow);
		
		JTextField jtf = new JTextField(20);//单行文本框
		jf.add(jtf);
		JButton jb = new JButton("Send");
		jf.add(jb);
			    
		JTextArea jta = new JTextArea();//多行文本框
	    jta.setPreferredSize(new Dimension(290,300));
	    jf.add(jta); 

	    jf.setVisible(true);
		
		Pass1 pass = new Pass1(jtf);
		Receive1 rec = new Receive1(jta);
		
		jb.addActionListener(pass);
		
		rec.start();
	}
}
//发送命令封装的类
public class Pass1  implements ActionListener{
	
	public JTextField jtf;
	public int localpost=13000;
	public int recpost=14000;
    public SocketAddress localAddr = new InetSocketAddress("192.168.31.28", localpost);
	public DatagramSocket dSender;
	
	public void actionPerformed(ActionEvent e) {
//		System.out.println(pass);
		send();

	}
	public Pass1(JTextField jtf){
		this.jtf = jtf;
		try {
			dSender = new DatagramSocket(localAddr);
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void send(){
		try {
			byte buffer[]= jtf.getText().getBytes() ;//3.要发送的数据
			 //4.发送数据的目标地址和端口
			SocketAddress destAdd = new InetSocketAddress("192.168.31.28", recpost);
			 //5.创建要发送的数据包,指定内容,指定目标地址
			DatagramPacket dp = new DatagramPacket(buffer, buffer.length, destAdd);
			dSender.send(dp);//6.发送
			System.out.println("Client1已发送: "+jtf.getText());
			 
		} catch (SocketException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}
//接收命令封装的类
public class Receive1 extends Thread{
	public JTextArea jta;
	public SocketAddress localAddr= new InetSocketAddress("192.168.31.28", 12000);
	public SocketAddress destAdd;
	public DatagramSocket recvSocket;
	
	public Receive1(JTextArea jta){
		this.jta = jta;
	}
	
	public void run(){
		//2.创建发送的Socket对象
		try {
			recvSocket = new DatagramSocket(localAddr);
//			while (true) {
				byte[] buffer1 = new byte[20]; // 3.指定接收缓冲区大小:每个包20字节
				// 4.创建接收数据包对象
				DatagramPacket packet1 = new DatagramPacket(buffer1, buffer1.length);
				System.out.println("Client1等待接收数据:");
				while (true) {
				//5.阻塞,等待数据到来,如果收到数据,存入packet中的缓冲区中
				recvSocket.receive(packet1); // 6.在此等待接收对方发的UDP包
				//得到发送方的IP和端口
				destAdd = packet1.getSocketAddress();
				System.out.println("Client1得到发送方的端口和IP:"+destAdd);
				// 转换接收到的数据为字符串
				String msg = new String(packet1.getData());
				// 接收到后,打印出收到的数据长度
				jta.append(msg + "\n");// 显示在文本框里
				System.out.println("recv is:" + msg + " from:" +"Client2");		
			}			
		} catch (SocketException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}
}

注意:在进行测试时,两台电脑应在同一wifi下进行连接测试,或是一台电脑在wifi下利用不同的收发端口自测。

界面显示结果为

Java聊天系统怎么做 java 聊天_Java聊天系统怎么做_02