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 ...
随机推荐
- linux下安装ffmpeg
1. 首先安装系统编译环境 yum install -y automake autoconf libtool gcc gcc-c++ #CentOS 2. 编译所需源码包 #yasm:汇编器,新版 ...
- Node.js学习笔记(四): 全局对象
在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性. 这 ...
- typeof关键字的作用
http://blog.chinaunix.net/uid-28458801-id-4200573.html 一.typeof详解: 前言: typeof关键字是C语言中的一个新扩展,这个特性在 ...
- 关于python使用threadpool中的函数单个参数和多个参数用法举例
1.对单个元素的函数使用线程池: # encoding:utf-8 __author__='xijun.gong' import threadpool def func(name): print 'h ...
- JavaScript 模块化历程
这是一篇关于js模块化历程的长长的流水账,记录js模块化思想的诞生与变迁,展望ES6模块化标准的未来.经历过这段历史的人或许会感到沧桑,没经历过的人也应该知道这段历史. 无模块时代 在ajax还未提出 ...
- 树和二叉树的存储结构的实现(C/C++实现)
存档: #include <iostream.h> #include <stdio.h> #include <stdlib.h> #define max 20 ty ...
- BZOJ:4873: [Shoi2017]寿司餐厅
4873: [Shoi2017]寿司餐厅 首先很开心在膜你赛的时候做了出来. 看到数据范围,看到不能dp,看到贡献去重后计算,咦,流? 那就容易了,转最大权闭合子图,每个区间建一个点,取了就一定要取他 ...
- UVA11636-Hello World!-水题
Hello World! Time limit: 1.000 seconds When you first made the computer to print the sentence "H ...
- Java学习之类的构建方法(函数)
在学习类的部分时,建立一个对象是这样建立的:(假设Person是类)Person p = new Person():我一直很费解为何new后面是一个函数形式, 今天学完构建方法后,才恍然大悟,豁然 ...
- 【Python】爬虫-Scrapy
[Scrapy] Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据. Scrapy用途广泛,可以用于数据挖掘.监测和自动化测试. Scrapy ...