计算机网络实验四:利用UDP协议实现点对点聊天

文章目录

  • 1. 简介
    • 1.1 功能
    • 1.2 技术
    • 1.3 流程
  • 2. 源码
    • 2.1 客户端1
    • 2.2 客户端2(与客户端1不同的只有端口号)
    • 2.3 服务端
  • 3. 运行
  • 4. 注意
    • 4.1 端口占用
    • 4.2 运行时注意事项

1. 简介

1.1 功能

一个服务端,两个客户端。客户端将消息发送到服务端,由服务端对消息进行转发。以实现两个客户端通过服务端进行点对点通信。

1.2 技术

  1. 语言:java
  2. DatagramPacket和DatagramSocket,实现模拟UDP协议(通过端口实现两个进程间的通信)

1.3 流程

客户端1(2)通过端口号找到服务端,将消息发送给服务端;服务端接收到消息后,将接收到的内容转发给客户段2(1)

2. 源码

2.1 客户端1

package Socket2;


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.*;
/*
模拟客户端 - 普通 Socket 实现
*/
public class Client1 {
	public static void main ( String [] args ) throws IOException {
		
		System.out.println("输入0,发送消息      输入1,接收消息      输入2,停止收发消息   ");
		//创建DatagramSocket对象
		DatagramSocket socket=new DatagramSocket(null);
		socket.bind(new InetSocketAddress(9999));//绑定本地端口
		System.out.println("正常1");
		//定义服务器的地址、端口号、数据
		InetAddress address=InetAddress.getByName("localhost");
		int port=9000;
		while(true)
		{
			
			Scanner input=new Scanner(System.in);
			int choose=input.nextInt();
			if(choose==0)
			{
				String inputdata=input.next();
				byte[] data=inputdata.getBytes("UTF-8");//拒绝乱码TT-TT
				//创建数据报
				DatagramPacket packet=new DatagramPacket(data, data.length, address, port);
				//向服务器端发送数据报
				socket.send(packet);
				System.out.println("正常2");
			}
			else if(choose==1)
			{
				byte[] data2=new byte[1024];
				DatagramPacket packet2=new DatagramPacket(data2, data2.length);
				//接收服务器响应的数据
				socket.receive(packet2);
				//读取数据
				String reply=new String(packet2.getData(),"UTF-8");
				System.out.println("接收消息:"+reply);
			}
			else if(choose==2)
			{
				//关闭资源
				socket.close();
				System.out.println("已结束");
			}
			else
			{
				System.out.println("请输入正确数字");
			}	
		}	
	}
}

2.2 客户端2(与客户端1不同的只有端口号)

package Socket2;


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.*;
/*
模拟客户端 - 普通 Socket 实现
*/
public class Client2 {
	public static void main ( String [] args ) throws IOException {
		
		System.out.println("输入0,发送消息      输入1,接收消息      输入2,停止收发消息   ");
		//创建DatagramSocket对象
		DatagramSocket socket=new DatagramSocket(null);
		socket.bind(new InetSocketAddress(9998));//绑定本地端口
		//定义服务器的地址、端口号、数据
		InetAddress address=InetAddress.getByName("localhost");
		int port=9000;
		while(true)
		{
			
			Scanner input=new Scanner(System.in);
			int choose=input.nextInt();
			if(choose==0)
			{
				String inputdata=input.next();
				byte[] data=inputdata.getBytes("UTF-8");//拒绝乱码TT-TT
				//创建数据报
				DatagramPacket packet=new DatagramPacket(data, data.length, address, port);
				//向服务器端发送数据报
				socket.send(packet);
			}
			else if(choose==1)
			{
				byte[] data2=new byte[1024];
				DatagramPacket packet2=new DatagramPacket(data2, data2.length);
				//接收服务器响应的数据
				socket.receive(packet2);
				//读取数据
				String reply=new String(packet2.getData(),"UTF-8");
				System.out.println("接收消息:"+reply);
			}
			else if(choose==2)
			{
				//关闭资源
				socket.close();
				System.out.println("已结束");
			}
			else
			{
				System.out.println("请输入正确数字");
			}	
		}	
	}
}

2.3 服务端

package Socket2;


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/*
      服务器端
      端口号9000
*/
public class Server 
{
	public static void main(String[] args) throws IOException
	{
		DatagramSocket socket=new DatagramSocket(9000);  //端口9000
		System.out.println("服务器端已经启动,等待客户端发送数据");
		byte[] data =new byte[1024];  
		DatagramPacket packet=new DatagramPacket(data, data.length); //指定接收包的大小为1024
		int finish=0;
		while(true)
		{
			//接收到数据报之前会一直阻塞
			socket.receive(packet);
			
			
			//读取数据
			String info=new String(packet.getData(),"UTF-8");
			System.out.println("-------------------------------------------");
			System.out.println("成功接收数据                                                         ");
			System.out.println("源端口号:"+packet.getPort());
			System.out.println("接收数据:"+info);
			System.out.println("-------------------------------------------");
			
			//向本机地址,指定端口的客户端发送数据
			InetAddress address=packet.getAddress();
			int port=packet.getPort();
			String message=new String (packet.getData(),"UTF-8");
			//指定发送端口
			int sendport=port;
			if(port==9999)
			{
				sendport=9998;
			}
			else
			{
				sendport=9999;
			}
			byte[] data2=message.getBytes("UTF-8");
			DatagramPacket packet2=new DatagramPacket(data2, data2.length, address, sendport);
			socket.send(packet2);
			System.out.println("-------------------------------------------");
			System.out.println("成功发送数据                                                         ");
			System.out.println("目的端口号:"+sendport);
			System.out.println("发送数据:"+message);
			System.out.println("-------------------------------------------");
			if(finish==1)
			{
				socket.close();
			}
		}
	}
}

3. 运行

(我使用的是eclipse,需要开三个结果窗口,并且三个源码在同一个包中

  1. 首先运行服务端,此时会显示已经打开服务端的提示信息,不需要进行任何操作,直接将结果窗口固定住。
  2. 运行客户端1,输入数字1,等待接收消息,将结果窗口固定住。
  3. 运行客户端2,输入数字0,选择发送消息功能。任意输入一条要发送的数据(比如“你好,我是客户端2”),按下enter键。固定住结果窗口
  4. 此时,服务端会接收到消息,并将数据转发给客户端1。在已经固定在服务端结果的结果界面中,可以观察到相关提示信息。
  5. 再看客户端1的结果窗口,已经接收到客户端2发送过来的信息。

此时已经成功完成了一次客户端2向客户端1发送消息。

4. 注意

4.1 端口占用

这三个程序都只能运行一次后持续开着,如果再次运行,会报错:端口被占用。这时需要打开资源管理器,将eclipse下的java进程结束,释放端口,才能再次运行。

4.2 运行时注意事项

按照顺序依次运行程序后,不需要再次点击运行。进程会一直保持开启并使用状态,结果可以通过开通三个结果窗口,每个窗口对应一个进程,可以观察到每个进程的持续性变化。

你可能感兴趣的:(编程,#,Java,计算机网络,java,socket,网络通信)