标题:UDP编写的聊天室
一、要求:实现,学生,老师相互聊天【双方都可以一边接收一边发送】
二、分析
假设老师,学生各有一个发送端,接收端
则老师需待学生发送完后,才能发送,学生也是如此
故需要使用多线程,实现相互聊天
三、示意图如下
四、具体操作,只是将接收端与发送端的通信封装成一个方法,线程体run里面,学生老师都开启两个线程即可。【其实就是在上一篇发送端,接收端持续通信那篇blog加了点多线程,封装,故此blog没有做过多的详细说明】
1)发送端
/*
*
互聊
测试手动输入,屏幕输出 ;从System.in读取,将字节数组发送;
方法一:BufferedInputStream is=new BufferedInputStream(System.in);
缺点,is.read(buf),buf的大小不好确定
方法二:BufferedReader is=new BufferedReader(new InputStreamReader(System.in));
缺点,第一次将字节流转成字符流,第二次将字符串转成字节发送
发送端:先读取【用BufferedInputStream(System.in)读取,每回读取多大?,或者说,用BufferedReader,每回读取一行,但需要转换流将字节流System.in转成字符流】,再写入到字节数组中【用ByteArrayOutputStream,直接写入到字节数组,方便,快捷】
原因,因为本来就用转换成字节数组,故用字节流,加上缓冲后更快,故BufferedInputStream
可以用BufferedOutputStream包装一个FileOutputStream,不过while循环,反复读取,数组大小,也不好定
*/
/**
* 1.使用DatagramSocket
* 2.准备数据
* 3.封装成DatagramPacket包裹,需指定目的地
* 4.释放资源 若是多线程,则最后释放资源
* @author dell
*
*/
public class TestUDPClientSystemIn06 extends Thread{
private String name;
private int port;//发送端端口
private int destPort;//接收端端口
public TestUDPClientSystemIn06(String name,int port,int destPort) {
this.name=name;
this.destPort=destPort;
this.port=port;
}
public void run() {
try {
// System.out.println(name+"为发送端,开始发送");
System.out.println("-----"+name+"界面--------");
//1.使用DatagramSocket
DatagramSocket ds=new DatagramSocket(port);//6666
// 2.准备数据
//2.1创建源
//2.2选择流
BufferedInputStream is=new BufferedInputStream(System.in);
//2.3操作
int len=0;
byte[] buf=new byte[1024];
String s="";
while(!s.equals("exit")) {//若接受到的为exit,则发送后【否则接收端,没有退出的条件】,退出
len=is.read(buf);
//3.封装成DatagramPacket包裹,需指定目的地
DatagramPacket dp=new DatagramPacket(buf,len,InetAddress.getByName("localhost"),destPort);//8888
ds.send(dp);
s=new String(buf,0,len-2);//因为\r\n也都进去了
}
//2.4释放
System.out.println("发送成功");
//* 4.释放资源 若是多线程,则最后释放资源
ds.close();
}catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
}
}
2)接收端
/**
* 互聊
* 测试手动输入,屏幕输出
*/
/**
* 1.使用DatagramSocket
* 2.准备容器 封装成DatagramPacket包裹
* 3.阻塞式接收包裹
* 4.分析数据
* 5.释放资源 若是多线程,则最后释放资源
* @author dell
*
*/
public class TestUDPServerSystemIn06 extends Thread{
private String name;
private int port;
public TestUDPServerSystemIn06(String name, int port) {
super();
this.name = name;
this.port = port;
}
public void run(){
// System.out.println("接收端,开始接收");
//1.使用DatagramSocket
DatagramSocket ds;
try {
ds = new DatagramSocket(port);//8888
// 2.准备容器 封装成DatagramPacket包裹
byte[] buf=new byte[1024*60];//接受的若大于此数组大小,problem? 与发送端对应即可
DatagramPacket dp=new DatagramPacket(buf,0,buf.length);
//3.阻塞式接收包裹 -->该方法阻塞,直到接收到数据报。
ds.receive(dp);
String str=new String(buf,0,dp.getLength()-2);//若不为exit则输出,否则退出当前循环
while(!str.equals("exit")) {
System.out.println(name+"-->"+str);//上一行,删去了换行符\r\n,故此处加上
dp=new DatagramPacket(buf,0,buf.length);
//3.阻塞式接收包裹 -->该方法阻塞,直到接收到数据报。
ds.receive(dp);
str=new String(buf,0,dp.getLength()-2);
}
//4.分析数据
System.out.println("接收完毕");
//5.释放资源 若是多线程,则最后释放资源
ds.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
}
}
3)学生界面
public class TestUDPStudent {
public static void main(String[] args) {
new TestUDPServerSystemIn06("老师",8888).start();//学生接收端口为8888,接收来自老师的信息
new TestUDPClientSystemIn06("学生",6666,7777).start();//学生发送端口为6666,发送信息的格式为:名字 学生,发送端口6666,目的接收端口 7777
}
}
4)老师界面
public class TestUDPTeacher {
public static void main(String[] args) {
new TestUDPServerSystemIn06("学生",7777).start();//老师接收端口为7777,接收来自学生的信息
new TestUDPClientSystemIn06("老师",5555,8888).start();//老师发送端口为5555,发送信息的格式为:名字 老师,发送端口5555,目的接收端口 8888
}
}