JAVA 多线程实现简单UDP一对一聊天
2017-12-01 02:31
513 查看
UDP:将数据及源和目的封装成数据包中,不需要建立连接每个数据报的大小在限制在64k内,因无连接,是不可靠协议不需要建立连接,速度快。
本文两端都用的本地ip。
百度解释:tcp/udp区别。
一般的聊天程序由于追求快捷的数据传输速度,而又不是比较关注数据的完整性,都是用UDP协议来传递数据,我们聊天的时候就像qq一样,一边打字发消息,一边也在接收消息。
要在程序中实现这种功能,那么就要用到多线程。其中一个线程用来专门接收数据,一个纯种用来专门发送数据。
下面我们就用多线程来实现这个功能:
既然是多线程,那么我们两个主函数里面肯定都有两个线程启动,一个发送,一个接收。
上代码:---------- :
线程类 1 Send 发送数据 :
线程类 2 Receive 接收数据
package com.socket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
*
* 接收消息线程
*
*/
public class Receive implements Runnable {
private DatagramSocket datagramSocket = null;
// 定义构造方法
Receive (DatagramSocket datagramSocket){
this.datagramSocket = datagramSocket;
}
// 线程
@Override
public void run() {
try {
while (true) {
// 定义一个1024到字节数组,用于存放发送过来到数据
byte[] data = new byte[1024];
// new 一个数据报
DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
// 阻塞等待数据发送过来
datagramSocket.receive(datagramPacket);
// 获取发送过来的数据的IP地址 和 端口号
String ip = datagramPacket.getAddress().getHostAddress();
int port = datagramPacket.getPort();
// 获取传送过来的数据
String out = new String(datagramPacket.getData(),0, datagramPacket.getLength());
// 如果传送过来的数据是 bye 那么跳出循环 不在接收消息 结束
if ("bye".equals(out)){
System.out.println(" 对方离开了 ! ");
break;
}
// 用来显示发送过来的 IP地址 端口号 内容
System.out.println("来自 ip : "+ip+" 端口号 : "+port + " 内容 : "+out);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
datagramSocket.close(); // 关闭资源
}
}
}
第一个主函数 UDPserver :
第二个主函数 UDPclient :
代码敲完,我们运行来看看结果:
这是UDPclient控制台
接着看UDPserver控制台
已经接收到了 UDPclient 输入的信息,那么我们现在从UDPserver回复几句
看到 UDPclient 收到没ok,收到了。
不想聊了,走了。UDPserver 看到“对方离开了” 回复“bye”
此时线程全部停止,程序运行结束。
此时我们注意到,我们的端口号是 55726 这些,是随机的,原因是:两个程序发送信息的DatagramSocket没有绑定端口,所以发送的信息的端口是随机的。
如果我们在两个主函数分别改为
UDPsever :
try {
DatagramSocket send = new DatagramSocket(7777);
DatagramSocket receive = new DatagramSocket(8888);
new Thread(new Receive(receive)).start(); //监听 8888 端口
new Thread(new Send(send,6666)).start(); // 给 6666 端口 发送数据
} catch (SocketException e) {
e.printStackTrace();
}
UDPclient :
try {
DatagramSocket send = new DatagramSocket(9999);
DatagramSocket receive = new DatagramSocket(6666);
new Thread(new Send(send,8888)).start();
new Thread(new Receive(receive)).start();
} catch (SocketException e) {
e.printStackTrace();
}
这样我们就会发现端口号不在随机,而是 7777 和 9999 了,图这个就不贴了。
最后,关于bufferedReader.readLine() 说两句 我们看见while循环的条件
string = bufferedReader.readLine() !=null ,为什么没有输入数据的时候还在循环里面呢? 原因在于readLine()是一个阻塞函数,当没有数据读取时,就会一直阻塞在那,而不是返回 null ,所以我们上面想要退出循环结束程序时, 要么关闭数据流 要么就break 出去。
最后最后,本人也是在校大学生,菜鸟一枚,大神勿喷,大佬有兴趣可以指点指点。
本人第一次写博客,才开始,准备记录自己的学习过程和经历。写的不好,见谅。
:):)
本文两端都用的本地ip。
百度解释:tcp/udp区别。
TCP---传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。 UDP---用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快
一般的聊天程序由于追求快捷的数据传输速度,而又不是比较关注数据的完整性,都是用UDP协议来传递数据,我们聊天的时候就像qq一样,一边打字发消息,一边也在接收消息。
要在程序中实现这种功能,那么就要用到多线程。其中一个线程用来专门接收数据,一个纯种用来专门发送数据。
下面我们就用多线程来实现这个功能:
既然是多线程,那么我们两个主函数里面肯定都有两个线程启动,一个发送,一个接收。
上代码:---------- :
线程类 1 Send 发送数据 :
package com.socket; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class Send implements Runnable { private DatagramSocket datagramSocket = null; private int port; // 定义构造方法 使其可以传入 DatagramSocket 和要访问的端口号,然后赋值给变量 Send (DatagramSocket datagramSocket, int port){ this.datagramSocket = datagramSocket; this.port = port; } // 线程 @Override public void run() { // 定义一个字符缓冲输入流 BufferedReader bufferedReader = null; try { bufferedReader = new BufferedReader(new InputStreamReader(System.in)); String string = null; //byte[] data1 = "欢迎你 ! ".getBytes(); while ((string = bufferedReader.readLine()) != null){ // 把输入的字符放入data里面 byte[] data = string.getBytes(); // 把要访问的ip地址,端口号 和 数据放入 DatagramPacket datagramPacket = new DatagramPacket(data, data.length, InetAddress.getByName("localhost"), port); // 发送数据报到指定 ip地址和端口号 datagramSocket.send(datagramPacket); // 这里是 : 如果控制台输入 bye 那么代表 跳出循环 不在发送数据 结束 if (string.equals("bye")) { // System.out.println("进入if"); break; } } //System.out.println("出来了"); } catch (IOException e) { e.printStackTrace(); } finally { try { if (bufferedReader != null) { bufferedReader.close(); //关闭流 } datagramSocket.close(); // 关闭资源 } catch (IOException e) { e.printStackTrace(); } } } }
线程类 2 Receive 接收数据
package com.socket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
*
* 接收消息线程
*
*/
public class Receive implements Runnable {
private DatagramSocket datagramSocket = null;
// 定义构造方法
Receive (DatagramSocket datagramSocket){
this.datagramSocket = datagramSocket;
}
// 线程
@Override
public void run() {
try {
while (true) {
// 定义一个1024到字节数组,用于存放发送过来到数据
byte[] data = new byte[1024];
// new 一个数据报
DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
// 阻塞等待数据发送过来
datagramSocket.receive(datagramPacket);
// 获取发送过来的数据的IP地址 和 端口号
String ip = datagramPacket.getAddress().getHostAddress();
int port = datagramPacket.getPort();
// 获取传送过来的数据
String out = new String(datagramPacket.getData(),0, datagramPacket.getLength());
// 如果传送过来的数据是 bye 那么跳出循环 不在接收消息 结束
if ("bye".equals(out)){
System.out.println(" 对方离开了 ! ");
break;
}
// 用来显示发送过来的 IP地址 端口号 内容
System.out.println("来自 ip : "+ip+" 端口号 : "+port + " 内容 : "+out);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
datagramSocket.close(); // 关闭资源
}
}
}
第一个主函数 UDPserver :
package com.socket; import java.net.DatagramSocket; import java.net.SocketException; public class UDPserver { public static void main(String[] args) { try { DatagramSocket send = new DatagramSocket(); DatagramSocket receive = new DatagramSocket(8888); //监听 8888 端口 new Thread(new Send(send,6666)).start(); // 给 6666 端口 发送数据 new Thread(new Receive(receive)).start(); // 监听 8888 端口 获取 从其他端口发送过来的数据 } catch (SocketException e) { e.printStackTrace(); } } }
第二个主函数 UDPclient :
package com.socket; import java.net.*; public class UDPclient { public static void main(String[] args) { try { DatagramSocket send = new DatagramSocket(); DatagramSocket receive = new DatagramSocket(6666); //监听 6666 端口 new Thread(new Send(send,8888)).start(); // 给 8888 端口发送数据线程 new Thread(new Receive(receive)).start(); // 监听 6666 端口 获取 从其他端口发送过来的数据 } catch (SocketException e) { e.printStackTrace(); } } }
代码敲完,我们运行来看看结果:
这是UDPclient控制台
接着看UDPserver控制台
已经接收到了 UDPclient 输入的信息,那么我们现在从UDPserver回复几句
看到 UDPclient 收到没ok,收到了。
不想聊了,走了。UDPserver 看到“对方离开了” 回复“bye”
此时线程全部停止,程序运行结束。
此时我们注意到,我们的端口号是 55726 这些,是随机的,原因是:两个程序发送信息的DatagramSocket没有绑定端口,所以发送的信息的端口是随机的。
如果我们在两个主函数分别改为
UDPsever :
try {
DatagramSocket send = new DatagramSocket(7777);
DatagramSocket receive = new DatagramSocket(8888);
new Thread(new Receive(receive)).start(); //监听 8888 端口
new Thread(new Send(send,6666)).start(); // 给 6666 端口 发送数据
} catch (SocketException e) {
e.printStackTrace();
}
UDPclient :
try {
DatagramSocket send = new DatagramSocket(9999);
DatagramSocket receive = new DatagramSocket(6666);
new Thread(new Send(send,8888)).start();
new Thread(new Receive(receive)).start();
} catch (SocketException e) {
e.printStackTrace();
}
这样我们就会发现端口号不在随机,而是 7777 和 9999 了,图这个就不贴了。
最后,关于bufferedReader.readLine() 说两句 我们看见while循环的条件
string = bufferedReader.readLine() !=null ,为什么没有输入数据的时候还在循环里面呢? 原因在于readLine()是一个阻塞函数,当没有数据读取时,就会一直阻塞在那,而不是返回 null ,所以我们上面想要退出循环结束程序时, 要么关闭数据流 要么就break 出去。
最后最后,本人也是在校大学生,菜鸟一枚,大神勿喷,大佬有兴趣可以指点指点。
本人第一次写博客,才开始,准备记录自己的学习过程和经历。写的不好,见谅。
:):)
相关文章推荐
- 黑马程序员-JAVA学习之用多线程实现简单UDP聊天程序
- JAVA 多线程实现聊天(UDP通信 )
- java多线程以及java网络编程实现简单的聊天系统
- java用socket和serversocket实现一对一聊天(java实现简单的TCP聊天程序)
- 多线程实现简单的一对一聊天
- Java网络----Socket, 多线程实现内网多人聊天及一对一聊天
- JAVA系列课程讲座二:使用Socket通信实现简单聊天通信程序(UDP方式)
- 一个UDP(多播)局域聊天的简单实现 (JAVA)
- JAVA简单多线程一对一聊天
- UDP实现简单图形界面多线程聊天
- 利用java UDP协议,实现简单的双人聊天
- java用ServerSocket类结合io流实现一对一聊天(java实现简单的TCP聊天程序只能用telnet连接后方可使用)
- JAVA学习第六十课 — UDP协议 &基于多线程模拟简单的QQ聊天程序
- java网络编程一:模拟qq聊天功能,实现一对一聊天
- Java 多线程的两种简单实现方法
- 用UDP实现简单的聊天功能
- Java多线程-一个简单的线程,实现挂起和恢复的功能
- java简单多线程方式+实现文件上传(spring mvc + jquery.form.js 框架)
- Java之Socket简单聊天实现(QQ续二)
- Socket UDP 简单聊天的实现