java 网络编程之UDP通信和简单的群聊程序
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #333;
background: #f8f8f8;
}
.hljs-comment,
.hljs-template_comment,
.diff .hljs-header,
.hljs-javadoc {
color: #998;
font-style: italic;
}
.hljs-keyword,
.css .rule .hljs-keyword,
.hljs-winutils,
.javascript .hljs-title,
.nginx .hljs-title,
.hljs-subst,
.hljs-request,
.hljs-status {
color: #333;
font-weight: bold;
}
.hljs-number,
.hljs-hexcolor,
.ruby .hljs-constant {
color: #099;
}
.hljs-string,
.hljs-tag .hljs-value,
.hljs-phpdoc,
.tex .hljs-formula {
color: #d14;
}
.hljs-title,
.hljs-id,
.coffeescript .hljs-params,
.scss .hljs-preprocessor {
color: #900;
font-weight: bold;
}
.javascript .hljs-title,
.lisp .hljs-title,
.clojure .hljs-title,
.hljs-subst {
font-weight: normal;
}
.hljs-class .hljs-title,
.haskell .hljs-type,
.vhdl .hljs-literal,
.tex .hljs-command {
color: #458;
font-weight: bold;
}
.hljs-tag,
.hljs-tag .hljs-title,
.hljs-rules .hljs-property,
.django .hljs-tag .hljs-keyword {
color: #000080;
font-weight: normal;
}
.hljs-attribute,
.hljs-variable,
.lisp .hljs-body {
color: #008080;
}
.hljs-regexp {
color: #009926;
}
.hljs-symbol,
.ruby .hljs-symbol .hljs-string,
.lisp .hljs-keyword,
.tex .hljs-special,
.hljs-prompt {
color: #990073;
}
.hljs-built_in,
.lisp .hljs-title,
.clojure .hljs-built_in {
color: #0086b3;
}
.hljs-preprocessor,
.hljs-pragma,
.hljs-pi,
.hljs-doctype,
.hljs-shebang,
.hljs-cdata {
color: #999;
font-weight: bold;
}
.hljs-deletion {
background: #fdd;
}
.hljs-addition {
background: #dfd;
}
.diff .hljs-change {
background: #0086b3;
}
.hljs-chunk {
color: #aaa;
}
#container {
padding: 15px;
}
pre {
border: 1px solid #ccc;
border-radius: 4px;
display: block;
background-color: #f8f8f8;
}
pre code {
white-space: pre-wrap;
}
.hljs,
code {
font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;
}
:not(pre) > code {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
background-color: #f9f2f4;
white-space: nowrap;
border-radius: 4px;
}
-->
UDP通信需要明确的几点:
- UDP通信不是面向连接的,发送端不管接收端是否启动是否能接收,发完数据报就结束。
- 无论是发送端还是接收端,都需要描述两个对象:套接字和数据报。
- 接收端的套接字对象中必须明确接收端口,且必须和发送端指定的目标端口一致。而发送端的套接字中则一般采用随机分配的发送端口。
- 无论是发送端还是接收端,数据报中都记录了自己和对方的socket信息(ip+port),还提供了用于发送或接收的数据缓冲区。这些数据只有数据报对象自己最清楚,如
getPort(),getAddress(),getData()等。- (1).只不过对于发送端来说,创建发送报文对象需要指定目标套接字信息(ip+port),还需明确数据发送缓冲区。
- (2).而对于接收端来说,则只需明确一个数据接收缓冲区即可。
- 接收端应该不断循环地负责接收。
- UDP套接字类DatagramSocket,UDP数据报类DatagramPacket。
UDPSender端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class UDPSender {
public static void main(String[] args) {
DatagramSocket dgs = null;
try {
// 1. 创建udp发送端的socket,一般使用随机发送端口
dgs = new DatagramSocket();
// 2. 创建udp报文包对象
// 2.1 创建数据发送缓冲区
String text = "Hello World! I'm coming";
byte[] buf = text.getBytes();
// 2.2 创建发送数据报文对象
InetSocketAddress isa = new InetSocketAddress("192.168.0.124",8888);
DatagramPacket dgp = new DatagramPacket(buf,buf.length,isa);
//DatagramPacket dgp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.0.124"), 8888);
// 3.发送udp报文
dgs.send(dgp);
} catch (SocketException e1) {
e1.printStackTrace();
} catch (UnknownHostException e2) {
e2.printStackTrace();
} catch (IOException e3) {
e3.printStackTrace();
} finally {
// 4. 关闭套接字
dgs.close();
}
}
}
UDPRecver端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UDPRecver {
public static void main(String[] args) {
while(true){
// 1.创建udp接收套接字,接收端必须指定正确的端口
DatagramSocket dgs = null;
try {
dgs = new DatagramSocket(8888);
// 2. 创建udp接收数据包对象
byte[] buf = new byte[1024];
DatagramPacket dgp = new DatagramPacket(buf, buf.length);
// 3.从套接字中接收数据到数据包中
dgs.receive(dgp);
// 4.展示udp发送端相关信息,包括发送的数据
String data = new String(dgp.getData(), 0, dgp.getLength());
String ip = dgp.getAddress().getHostAddress();
int port = dgp.getPort();
System.out.println("Data: "+data+" ip: "+ip+" port: "+port);
} catch (SocketException s) {
s.printStackTrace();
} catch (IOException i) {
i.printStackTrace();
} finally {
dgs.close();
}
}
}
}
UDP实现群聊:
思路:
- 一个线程负责发,一个线程负责收,因此使用多线程。
- 发送端的数据报目标端应该指定为广播目标。且发送的数据来源于键盘输入。
- 接收端要无限循环接收数据,但应该提供下线离开功能。(假设收到了"bye",就表示下线)
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
public class QunChat {
public static void main(String[] args) throws SocketException {
//发送端和接收端套接字,接收端套接字端口为8888,需要传递给发送端的报文对象
DatagramSocket send_socket = new DatagramSocket();
DatagramSocket recv_socket = new DatagramSocket(8888);
Sender sender = new Sender(send_socket,8888);
Recver recver = new Recver(recv_socket);
Thread send_thread1 = new Thread(sender);
Thread recv_thread1 = new Thread(recver);
send_thread1.start();
recv_thread1.start();
}
}
class Sender implements Runnable {
private DatagramSocket send_sock;
private int dest_port;
Sender(DatagramSocket s,int port){ //初始化时就指定目标端口
this.send_sock = s;
this.dest_port = port;
}
public void run() {
while(true) {
try {
//群聊发送目标,以广播为例
InetSocketAddress isa = new InetSocketAddress("192.168.0.255", dest_port);
//从键盘接收数据
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line;
while((line=bufr.readLine())!=null) {
//如果发送的是bye,则断开,且不发送给接收端
if(line.equals("bye")) break;
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length, isa);
send_sock.send(dp);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
send_sock.close();
}
}
}
}
class Recver implements Runnable {
private DatagramSocket recv_sock;
Recver(DatagramSocket socket){
this.recv_sock = socket;
}
public void run() {
while(true) {
try {
//接收报文对象
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
recv_sock.receive(dp);
String src_ip = dp.getAddress().getHostAddress();
String data = new String(dp.getData(),0,dp.getLength());
if(data.equals("bye")) System.out.println(src_ip +" leaving");;
System.out.println("Recviving data: "+ data+" from "+src_ip );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
注:若您觉得这篇文章还不错请点击右下角推荐,您的支持能激发作者更大的写作热情,非常感谢!
java 网络编程之UDP通信和简单的群聊程序的更多相关文章
- java 网络编程之TCP通信和简单的文件上传功能
*/ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...
- Java网络编程之UDP
Java网络编程之UDP 一.C/S架构中UDP网络通信流程 ①创建DatagramSocket与DatagramPacket对象 ②建立发送端,接收端 ③建立数据包 ④调用Socket的发送.接收方 ...
- java网络编程之UDP通讯
详细介绍了java中的网络通信机制,尤其是UDP协议,通过对UDP的基本使用进行举例说明如何使用UDP进行数据的发送接收,并举了两个小demo说明UDP的使用注意事项. UDP协议原理图解: UDP协 ...
- Java网络编程之TCP通信
一.概述 Socket类是Java执行客户端TCP操作的基础类,这个类本身使用代码通过主机操作系统的本地TCP栈进行通信.Socket类的方法会建立和销毁连接,设置各种Socket选项. Server ...
- java网络编程之UDP实例
package Socket; import java.net.DatagramPacket; import java.net.InetAddress; public class Dgram { pu ...
- Java网络编程之TCP、UDP
Java网络编程之TCP.UDP 2014-11-25 15:23 513人阅读 评论(0) 收藏 举报 分类: java基础及多线程(28) 版权声明:本文为博主原创文章,未经博主允许不得转载. ...
- 网络编程之UDP编程
网络编程之UDP编程 UDP协议是一种不可靠的网络协议,它在通信的2端各建立一个Socket,但是这个Socket之间并没有虚拟链路,这2个Socket只是发送和接受数据的对象,Java提供了Data ...
- Java网络编程之URLConnection
Java网络编程之URLConnecton 一.URLConnection简介 URLConnection是一个抽象类,表示指向URL指定资源的活动连接.URLConnection有两个不同但相关的用 ...
- Java网络编程之InetAddress浅析
Java网络编程之InetAddress浅析 一.InetAddress综述 IP地址是IP使用的32位(IPv4)或者128位(IPv6)位无符号数字,它是传输层协议TCP,UDP的基础.InetA ...
随机推荐
- 用Vue开发一个实时性时间转换功能,看这篇文章就够了
前言 最近有一个说法,如果你看见某个网站的某个功能,你就大概能猜出背后的业务逻辑是怎么样的,以及你能动手开发一个一毛一样的功能,那么你的前端技能算是进阶中高级水平了.比如咱们今天要聊的这个话题:如何用 ...
- 微信小程序--合法域名校验出错
第一次做小demo的时候遇到一个问题,合法域名校验出错: 第一步:登陆微信公众号平台--个人中心--设置--开发设置--服务器域名(一个月只有5次修改机会一定要珍惜) 第二步 打开微信开发者工具,有个 ...
- PEP8 Python 编码规范整理
一 代码编排1 缩进.4个空格的缩进(编辑器都可以完成此功能),不使用Tap,更不能混合使用Tap和空格.2 每行最大长度79,换行可以使用反斜杠,最好使用圆括号.换行点要在操作符的后边敲回车.3 类 ...
- deeplearning.ai 人工智能行业大师访谈 Andrej Karpathy 听课笔记
1. 本科的时候在多伦多大学上Geoffrey Hinton的课,在MNIST数字数据集上训练受限玻尔兹曼机,觉得很有趣.后来在UBC读硕士,上了另一门机器学习的课,那是他第一次深入了解神经网络的相关 ...
- Javac编译时出现包不存在的报错的解决方案
今天在学习包类调用时出现如下错误: packa包不存在,在C盘目录下应该有这个包啊 原因是在当前目录下没找到,因为packa存放在其它目录下 如何解决: 应该配置一个classpath,直接把包所在的 ...
- HDU5447 Good Numbers
http://acm.hdu.edu.cn/showproblem.php?pid=5447 网上好像只找到java的题解,写完就发一下c++代码咯,顺便纪念一下+存个int128板子 做法可以看tj ...
- hdu_1011(Starship Troopers) 树形dp
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1011 题意:打洞洞收集脑子,你带领一个军队,洞洞互联成一棵树,每个洞中有一些bug,要全部杀死这些虫子 ...
- MYSQL数据库增量备份
MySQL数据库增量备份,在这之前修改我们的数据库配置文件/etc/my.cnf开启bin-log日志功能即可.接下来是我参考了下网上的一些方法,自己写的,主要还是要能学到他的一些思路和方法. #fu ...
- SQL强化(三) 自定义函数
---恢复内容开始--- Oracle中我们可以通过自定义函数去做一些逻辑判断,这样可以减少查询语句,提高开发效率 create -- 创建自定义函数 or replace -- 有同名函数就替换, ...
- 好的Qt学习资料
1.青春不老,奋斗不止!---CSDN博客地址http://blog.csdn.net/liang19890820: