版本1
简介
发送端可多次向接受端发送数据,接收端可多次接收数据,但发送端不可接收数据,接收端不可发送数据。
无实用价值,但存在一个问题:使用了字节缓冲流BufferedReader(InputStreamReader(System.in,“UTF-8”))从控制台读入数据,然后转为字节数组,封装为包裹后发送给接收端,接收端接收到包裹,获取字节数组,然后转为字符串,这时候如果发送端发送的是汉语,接收端得到的字符串则不会显示正确的发送信息,如果是英语或数字则不会存在此问题。对于从控制台读入数据,使用Scanner读入后,也会发生此问题。但如果不经过读入操作,直接在程序中设置一个String常量(String msg = “你好”;),然后将其作为数据发出,则不会出现问题。
代码
接收端
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* 双机通信
* 服务器端
* @author dxt
*
*/
public class UdpTalkServer {
public static void main(String[] args) throws IOException{
System.out.println("服务器端启动中......");
//1. 创建socket
DatagramSocket server = new DatagramSocket(9999);
while(true){
//准备容器
byte[] container = new byte[1024 * 60];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
//接收数据
server.receive(packet);
//分析数据
byte[] datas = packet.getData();
int len = packet.getLength();
String data = new String(datas, 0, len);
System.out.println(data); //简单输出
/*
//另一种方式输出
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out, "UTF-8"));
writer.write(data);
writer.flush();
*/
if(data.equals("bye")){ //跳出循环
break;
}
}
//5. 释放资源
server.close();
}
}
发送端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
/**
* 双机通信
* 客户端
* @author dxt
*
*/
public class UdpTalkClient {
public static void main(String[] args) throws IOException{
System.out.println("发送方启动中......");
//1. 建立socket
DatagramSocket client = new DatagramSocket(8888);
//2. 接收数据,也可以使用Scanner
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
while(true){
String msg = reader.readLine(); //存在问题,如果读入的是汉语文字,则会出现乱码或字符集不对应问题,不知道是什么原因
//String msg = "你好";
byte[] datas = msg.getBytes();
//打包
DatagramPacket packet =
new DatagramPacket(datas, 0, datas.length, new InetSocketAddress("127.0.0.1", 9999));
//发送
client.send(packet);
//退出循环
if(msg.equals("bye")){
break;
}
}
//释放资源
client.close();
}
}
版本2
简介
实现双方自由交流。
保留版本1中,汉字传输后格式不对问题。
代码
发送数据实现
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.Scanner;
/**
* 实现向对方发送数据
* 由于要一边发送,一边接收信息,所以需要创建线程来发送数据
* 通过实现Runnable接口来实现
* @author dxt
*
*/
public class TalkSend implements Runnable{
//发送方 socket
private DatagramSocket sender;
//发送方使用端口
private int port;
//接收端的IP
private String toIP;
//接受端的Port
private int toPort;
public TalkSend(int port, String toIP, int toPort){
super();
this.port = port;
this.toIP = toIP;
this.toPort = toPort;
try {
sender = new DatagramSocket(port); //初始化发送方
} catch (SocketException e) {
e.printStackTrace();
}
}
public void run(){
while(true){
Scanner scan = new Scanner(System.in);
String msg = scan.nextLine();
byte[] datas = msg.getBytes();
//打包
DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress(toIP, toPort));
//发送
try {
sender.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
//退出
if(msg.equals("bye")){
break;
}
}
this.sender.close();
}
}
接收数据实现
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* 实现接受发送方发来的数据
*
* @author dxt
*
*/
public class TalkReceive implements Runnable{
//接收端socket
DatagramSocket receiver;
//接收端口
int port;
//数据来源姓名
String name;
public TalkReceive(int port, String name){
super();
this.port = port; //初始化端口
this.name = name; //初始化姓名
try {
receiver = new DatagramSocket(port); //初始化socket
} catch (SocketException e) {
e.printStackTrace();
}
}
/**
* 实现run()方法
*/
public void run(){
while(true){
//准备数据容器,将容器封装为包裹
byte[] container = new byte[1024 * 32]; //32k
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
//接收包裹
try {
this.receiver.receive(packet);
} catch (IOException e) {
e.printStackTrace();
}
//分析数据
byte[] datas = packet.getData();
int len = packet.getLength();
String msg = new String(datas, 0, len);
System.out.println(this.name + ": " + msg);
//退出
if(msg.equals("bye")){
System.out.println(this.name + "--关闭连接 ");
break;
}
}
this.receiver.close();
}
}
第一个人
/**
* 进行UDP通话的其中一人
* 6666端口作为PersonOne的发送数据端口
* 7777端口作为PersonOne的接受数据端口,即数据要发送到7777端口
* @author dxt
*
*/
public class PersonOne {
public static void main(String[] args){
//注意,线程间的启动顺序是不确定的
//1. 发起通话
new Thread(new TalkSend(6666, "localhost", 9999)).start();
//2. 接收数据
new Thread(new TalkReceive(7777, "p2")).start();
}
}
另一个人
/**
* 进行UDP通话的另外一人
* 8888端口作为PersonTwo的发送数据端口
* 9999端口作为PersonOne的接受数据端口,即数据要发送到9999端口
* @author dxt
*
*/
public class PersonTwo {
public static void main(String[] args){
//注意,线程间的启动顺序是不确定的
//1. 发起通话
new Thread(new TalkSend(8888, "localhost", 7777)).start();
//2. 接收数据
new Thread(new TalkReceive(9999, "p1")).start();
}
}