Java---net(网络编程)---UDP聊天程序

需求:

通过键盘录入获取要发送的信息。

将发送和接收分别封装到两个线程中。

代码:

发送信息的 Runnable实现类:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Scanner;
/**
 * 2018年5月7日 下午7:25:49
 * @author <a href="mailto:[email protected]">宋进宇</a>
 *	UDP聊天程序
 *	通过键盘录入获取要发送的信息。
 *	将发送和接收分别封装到两个线程中。
 *	接收端 线程
 */
public class SendThread implements Runnable {
	DatagramSocket ds = null; //用来发送数据报的套接字
	InetAddress receiverIp = null; //接收端的IP
	int receicerPort = -1 ; //接收端的端口号
	/**
	 * 构造方法,需要传入 用来发送 数据报的套接字--ds,接收端的Ip--receiverIp,接收端的端口号--receicerPort
	 * @param ds 发送数据报的套接字
	 * @param receiverIp 接收端的IP
	 * @param receicerPort 接收端的端口号
	 */
	public SendThread( DatagramSocket ds, InetAddress receiverIp, int receicerPort ) {
		this.ds = ds;
		this.receiverIp = receiverIp;
		this.receicerPort = receicerPort;
	}
	
	@Override
	public void run() {
		//获得控制台输入流
		Scanner sc = new Scanner( System.in );
		//通过 ctrl+z 退出发送
		while ( sc.hasNext() ) {
			//读取一行消息
			String mes = sc.nextLine();
			//当发生消息为  over! 结束发送
			if ( "over!".equals( mes ) ) {
				break;
			}
			DatagramPacket dp = null;
			try {
				//把消息进行编码
				//把 消息的字节码 、接收端Ip和接收端端口号 封装成一个 数据报 包
				byte[] buf = mes.getBytes( "UTF-8" );
				//把 消息的字节码 、接收端Ip和接收端端口号 封装成一个 数据报 包
				dp = new DatagramPacket( buf, buf.length, receiverIp, receicerPort );
				
				//通过 发送数据报的套接字 进行发送
				ds.send( dp );
			} catch (IOException e) {
				break;
			}	
		}
		sc.close();
		ds.close();
	}
	
	//测试
	public static void main(String[] args){
		DatagramSocket senderDs = null;
		try {
			//创建 发送端的 数据报套接字
			senderDs = new DatagramSocket();
		} catch (SocketException e) {
			return;
		}
		try {
			//创建一个发送端线程
			Thread sender = new Thread( 
								new SendThread( senderDs, InetAddress.getByName( "127.0.0.1" ), 8888 ) );
			//启动线程 进行 发送消息
			sender.start();
		} catch (UnknownHostException e) {
			return ;
		}
	}
}

接收信息的 Runnable实现类:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**
 * 2018年5月7日 下午7:25:43
 * @author <a href="mailto:[email protected]">宋进宇</a>
 *	UDP聊天程序
 *	通过键盘录入获取要发送的信息。
 *	将发送和接收分别封装到两个线程中。
 *	发送端 线程
 */
public class ReceiveThread implements Runnable{
	DatagramSocket ds = null; //接收端的 数据报套接字
	int port = -1; //接收端的端口号
	/**
	 * 构造方法,传入接收端的 数据报套接字--ds和接收端的端口号--port
	 * @param ds 数据报套接字
	 * @param port 端口号
	 */
	public ReceiveThread(DatagramSocket ds, int port) {
		this.ds = ds;
		this.port = port;
	}


	@Override
	public void run() {
		//只要 发送端 有发送消息 接收端就处理
		while ( true ) {
			//创建一个用来接收的数据报的字节数组
			byte[] buf = new byte[1024];
			//封装 一个 接收 数据报 的包
			DatagramPacket dp = new DatagramPacket( buf, buf.length );
			try {
				//等待 发送端发送消息
				ds.receive( dp ); //这里是阻塞的
				//能到这里 说明发送端发来消息了
				//先获取 发送端的 ip
				InetAddress senderIp = dp.getAddress();
				//把 消息的字节数组 进行 解析
				String mes = new String( dp.getData(), 0, dp.getLength(), "UTF-8" );
				//在控制台 打印 发送端的地址 和 消息内容
				System.out.println( senderIp.getHostAddress() + ":" + mes );
			} catch (IOException e) {
				break;
			}
		}
	}
	
	//测试
	public static void main(String[] args){
		DatagramSocket receiveDs = null;
		try {
			//创建一个 接收 数据报的套接字
			receiveDs = new DatagramSocket( 8888 );
		} catch (SocketException e) {
			return;
		}
		//创建一个 接收端线程
		Thread receicer = new Thread( 
							  new ReceiveThread( receiveDs , receiveDs.getLocalPort() ) );
		//启动 接收端线程
		receicer.start();
	}
}

用户1:

import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class User1 {
	//这里为了代码 简洁 直接抛异常
	public static void main(String[] args) throws IOException {
		//自己用来发送数据报的端口号 10087
		DatagramSocket sendDs = new DatagramSocket(10087);
		InetAddress receiverIp = InetAddress.getByName( "127.0.0.1" );
		//对方用来接收数据报的端口号
		int receicerPort = 10001;
		Thread send = new Thread( new SendThread( sendDs, receiverIp, receicerPort ) );
		
		//自己的用来接收数据报 的 端口号 10086
		DatagramSocket receiveDs = new DatagramSocket(10086);
		Thread receive = new Thread( new ReceiveThread( receiveDs, 10086 ) ) ;
		
		send.start();
		receive.start();
	}
}

用户2:

import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class User2 {
	//这里为了代码 简洁 直接抛异常
	public static void main(String[] args) throws IOException {
		//自己用来发送数据报的端口号 10000
		DatagramSocket sendDs = new DatagramSocket(10000);
		InetAddress receiverIp = InetAddress.getByName( "127.0.0.1" );
		//对方用来接收数据报的端口号
		int receicerPort = 10086;
		Thread send = new Thread( new SendThread( sendDs, receiverIp, receicerPort ) );
		
		//自己用来接收数据报的端口号 10001
		DatagramSocket receiveDs = new DatagramSocket(10001);
		Thread receive = new Thread( new ReceiveThread( receiveDs, 10001 ) ) ;
		
		send.start();
		receive.start();
	}
}

注意:每个用户都需要 能够发送和接收的Runnable实现类。


猜你喜欢

转载自blog.csdn.net/qq_34928644/article/details/80275367