通过Socket实现UDP编程

UDP通信:

1、UDP协议(用户数据报协议)是无连接、不可靠、无序的。

2、UDP协议以数据报作为数据传输的载体。

3、使用UDP进行数据传输时,首先需要将要传输的数据定义成数据报(Datagram),在数据报中指明所要达到的Socket(主机地址和端口号),然后在将数据报发生出去。

4、相关操作类:

  • DatagramPacket:表示数据报包
  • DatagramSocket:进行端到端通信的类

一、DatagramPacket&DatagramSocket类的常用方法

<DatagramPacket类>

构造方法:

 DatagramPacket(byte[] buf,int length)//接受长度为length的数据包
DatagramPacket(byte[] buf,int length,InetAddress address,int port)//将指定长度的字节发生到指定主机的指定端口

<DatagramSocket类>

构造方法:

  DatagramSocket();
DatagramSocket(int port,InetAddress laddr);

常用方法:

  close();//关闭DatagramSocket
getInetAddress();//获取地址
getPort();//获取端口号
send(DatagramPacket p);//从此套接字发送数据包
recrive(DatagramPacket p);//从此套接字接收数据包

二、编程实现基于UDP的用户登录小程序

通过写一个用户登录的小程序,来直观了解基于UDP的Socket通信的工作过程,首先我们得知道在客户端和服务器通信时,两者的运作流程是如何的,先从服务器入手。

服务器端实现步骤:

1、创建DatagramSocket,指定端口号

2、创建DatagramPacket

3、接收客户端发送的数据信息

4、读取数据

那么用户登录的测试案例的服务器端类可以这样(待完善):

 public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub try {
//1.创建服务器端DatagramSocket,指定端口
DatagramSocket ds=new DatagramSocket(8080);
//2.创建数据报DatagramPacket,用于接收客户端发送的数据
byte[] data=new byte[1024];//创建字节数组,指定接受的数据报大小
DatagramPacket dp=new DatagramPacket(data, data.length);
//3.接收客户端发送的数据
ds.receive(dp);//此方法在接收到数据报之前会一直阻塞
//4.读取数据
//String info=Arrays.toString(data);
String info=new String(data, 0, dp.getLength());
System.out.println("我是服务器,客户端说:"+info);
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

接着我们看一下客户端的运作过程,其实和服务器端差不多,但是其中的区别还是要清楚的。

客户端实现步骤:

1、定义发送信息

2、创建DatagramPacket:包含将要发送信息

3、创建DatagramSocket

4、发送数据

那么用户登录的测试案例的客户端类可以这样(待完善):

 public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
//1.定义服务器的地址、端口号、数据
InetAddress add=InetAddress.getByName("localhost");
int port=8080;
byte[] data="用户名:admin;密码:123".getBytes();
//2.创建数据报,包含了发送的相关信息
DatagramPacket ap=new DatagramPacket(data, data.length, add, port);
//3.创建DatagramSocket对象
DatagramSocket ds=new DatagramSocket();
//4.向服务器端发送数据报
ds.send(ap); }

这样服务端和客户端就能进行最简单的通信了,目前这个还不能实现交互,下面会讲两者的交互。

运行一下,看看服务器端是否能接收到客户端发送的信息了呢...

分别启动服务器和客户端,注意必须先启动服务器再启动客户端,否则客户端找不到资源报错:


完善用户登录之服务器响应客户端

在上述的例子中,服务器和客户端仅仅只是相互可以通信,但服务器对于接收到的客户端信息并没有向客户端响应,客户端没有接收到服务器端的任何信息,这明显是不完善不友好的,在这里将对刚刚的例子进行完善,完成服务器对客户端的响应。

修改后的服务器端:

 public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub try {
/*
* 接收客户端发送的数据
*/
//1.创建服务器端DatagramSocket,指定端口
DatagramSocket ds=new DatagramSocket(8080);
//2.创建数据报DatagramPacket,用于接收客户端发送的数据
byte[] data=new byte[1024];//创建字节数组,指定接受的数据报大小
DatagramPacket dp=new DatagramPacket(data, data.length);
//3.接收客户端发送的数据
System.out.println("服务器端已启动,等待客户端发送数据...");
ds.receive(dp);//此方法在接收到数据报之前会一直阻塞
//4.读取数据
//String info=Arrays.toString(data);
String info=new String(data, 0, dp.getLength());
System.out.println("我是服务器,客户端说:"+info);
/*
* 响应客户端
*/
//1.定义客户端的地址、端口号、数据
InetAddress add=dp.getAddress();
int port=dp.getPort();
byte[] data2="欢迎您!".getBytes();
//2.创建数据报,包含响应的数据信息
DatagramPacket dp2=new DatagramPacket(data2, data2.length, add, port);
//3.响应客户端
ds.send(dp2);
//4.关闭资源
ds.close(); } catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

修改后的客户端:

 public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
/*
* 向服务器发送数据
*/
//1.定义服务器的地址、端口号、数据
InetAddress add=InetAddress.getByName("localhost");
int port=8080;
byte[] data="用户名:admin;密码:123".getBytes();
//2.创建数据报,包含了发送的相关信息
DatagramPacket ap=new DatagramPacket(data, data.length, add, port);
//3.创建DatagramSocket对象
DatagramSocket ds=new DatagramSocket();
//4.向服务器端发送数据报
ds.send(ap);
/*
* 接收服务器端的响应
*/
//1.创建数据报DatagramPacket,用于接收服务器发送的数据
byte[] data2=new byte[1024];
DatagramPacket dp2= new DatagramPacket(data2, data2.length);
//2.接收响应
ds.receive(dp2);
//3.读取数据
String info=new String(data2, 0, dp2.getLength());
System.out.println("我是客户端,服务器说:"+info);
//4.关闭资源
ds.close();
}

运行结果:

三、使用多线程实现多客户端的通信

应用多线程来实现服务器与多客户端之间的通信。<关于多线程更多的内容以后再总结>

多线程基本步骤:

1.服务器端创建DatagramSocket,循环调用receive()等待客户端发送数据报。

2.客户端创建一个DatagramSocket发送数据报到服务器端。

3.服务器端接收客户端的数据报,创建DatagramPacket与该客户建立专线接收数据报。

4.建立交互数据报在一个单独的线程上对话。

5.服务器端继续等待新的数据报。

------------------------------------------------------------------------------

下面再将上述的例子修改成多线程的通信

新建一个服务器线程处理类UDPServerThread,该类继承Thread类:

 /*
* 服务器线程处理类
*/
public class UDPServerThread extends Thread {
DatagramSocket ds=null;
DatagramPacket dp=null;
public UDPServerThread(DatagramSocket ds,DatagramPacket dp){
this.ds=ds;
this.dp=dp;
} public void run(){ try {
/*
* 接收客户端发送的数据
*/ //4.读取数据
//String info=Arrays.toString(data);
byte[] data=dp.getData();
String info=new String(data, 0, dp.getLength());
System.out.println("我是服务器,客户端说:"+info);
/*
* 响应客户端
*/
//1.定义客户端的地址、端口号、数据
InetAddress add=dp.getAddress();
int port=dp.getPort();
byte[] data2="欢迎您!".getBytes();
//2.创建数据报,包含响应的数据信息
DatagramPacket dp2=new DatagramPacket(data2, data2.length, add, port);
//3.响应客户端
ds.send(dp2); } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}

服务器端:

 /*
* 服务器端
*/
public class UDPSever { public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub try { // 1.创建服务器端DatagramSocket,指定端口
DatagramSocket ds = new DatagramSocket(8080);
System.out.println("服务器即将启动,等待客户端的连接...");
byte[] data = new byte[1024];
// 记录客户端的数量
int count = 0;
// 循环侦听等待客户端的连接
while (true) {
DatagramPacket dp = new DatagramPacket(data, data.length);
ds.receive(dp);
// 创建一个新的线程
UDPServerThread udp = new UDPServerThread(ds, dp);
// 启动线程,执行与客户端的交互
udp.start();
count++;
System.out.println("此时客户端数量为:" + count);
InetAddress add = dp.getAddress();
System.out.println("当前客户端的ip地址为" + add.getHostAddress());
} } catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }

多个客户端的运行结果:

这样一个简单的多线程UDP通信就完成了。

四、UDP和TCP

<解 惑>TCP和UDP编程都用在什么地方?

<回 答>网络通信,例如QQ客户端和服务器间的通信。

TCP是面向连接的、可靠的,如果对通信数据的可靠性要求比较高,确保数据对方可以收到,可以使用TCP。

UDP是无连接的,在通信前不会预先建立连接,无法保证可靠性,一般用于对数据可靠性要求不是那么高的场合。

<解 惑>UDP和TCP相比较有什么优缺点?

<回 答>UDP相较于TCP,不需要进行复杂的设定输入输出流,只需要设定数据报,即DatagramPacket。而TCP的发送以及接收消息,是通过socket.getInputStream()或者getOutputStream()方法,而UDP是直接设置了,DatagramSocket,通过其send()或者receive()方法来接收或发送消息。TCP的关键组成有server端的ServerSocket.accept()方法,这个方法是直到接收到了客户端的连接才会返回一个Socket,用于接下来的输入和输出。

所以说,TCP的数据传输是需要提前连接、三方握手,数据传输非常安全;

而UDP是不需要提前连接的,无需等待对方回答,所以不保证数据不丢失。

---------------点击查看更多关于Socket信息------------------

【Socket编程】通过Socket实现UDP编程的更多相关文章

  1. 【网络编程1】网络编程基础-TCP、UDP编程

    网络基础知识 网络模型知识 OSI七层模型:(Open Systems Interconnection Reference Model)开放式通信系统互联参考模型,是国际标准化组织(ISO)提出的一个 ...

  2. 62 网络编程(三)——UDP编程

    UDP编程标准步骤 服务器端 使用DatagramSocket创建服务端:DatagramSocket server = new DatagramSocket(port);//参数为自定义端口号 准备 ...

  3. Python学习笔记(四十六)网络编程(2)— UDP编程

    摘抄:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014320049779 ...

  4. python socket 编程(TCP与UDP)

    实验环境:python2 一.TCP编程 1.建立TCP服务器 ①创建TCPServer.py文件 ②编写服务器代码 1)创建socket对象,调用socket构造函数 2)绑定ip端口(IP号和端口 ...

  5. Linux网络编程——原始套接字编程

    原始套接字编程和之前的 UDP 编程差不多,无非就是创建一个套接字后,通过这个套接字接收数据或者发送数据.区别在于,原始套接字可以自行组装数据包(伪装本地 IP,本地 MAC),可以接收本机网卡上所有 ...

  6. linux网络编程-(socket套接字编程UDP传输)

    今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...

  7. Socket编程实践(12) --UDP编程基础

    UDP特点 无连接,面向数据报(基于消息,不会粘包)的传输数据服务; 不可靠(可能会丢包, 乱序, 反复), 但因此普通情况下UDP更加高效; UDP客户/服务器模型 UDP-API使用 #inclu ...

  8. Linux socket网络编程基础 tcp和udp

    Socket TCP网络通信编程 首先,服务器端需要做以下准备工作: (1)调用socket()函数.建立socket对象,指定通信协议. (2)调用bind()函数.将创建的socket对象与当前主 ...

  9. python网络-Socket之udp编程(24)

    一.udp简介 udp --- 用户数据报协议,是一个无连接的简单的面向数据报的运输层协议. udp不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地. udp在 ...

随机推荐

  1. 汇编总结:mov指令

    mov指令的作用: mov指令可能是汇编里用的最多的指令了,完成c语言里的赋值. mov指令种类: 1.普通的mov指令 2.做符号扩展的movs 3.做零扩展的movz 1.普通mov的种类有: m ...

  2. SpringMVC注解@RequestMapping之produces属性导致的406错误

    废话不多说,各位,直接看图说话,敢吗?这个问题网上解决的办法写的狠是粗糙,甚至说这次我干掉它完全是靠巧合,但是也不否认网上针对406错误给出的解决方式,可能是多种情况下出现的406吧?我这次的流程就是 ...

  3. SQl语句收藏(转)

    /* 启动MySQL */ net start mysql /* 连接与断开服务器 */ mysql -h 地址 -P 端口 -u 用户名 -p 密码 /* 跳过权限验证登录MySQL */ mysq ...

  4. 【Spring 核心】装配bean(三)XML配置

    项目包结构: src/main/java com.bonc.pojo--|-CompactDisc.java (接口) |-SgtPeppers.java     (实现类 实现 CompactDis ...

  5. 九天学会Java,第二天,算术运算

    算术运算 先回顾上次我们提到的编程特性 变量和数据类型,赋值和输出 算术运算 选择结构 循环结构 函数定义,函数调用 变量作用域 栈,程序运行的基石 面向对象 异常处理 语言提供的公用包 第一天我们讲 ...

  6. 使用xorm工具,根据数据库自动生成 go 代码

    使用xorm工具,根据数据库自动生成 go 代码 引入 使用 golang 操作数据库的同学都会遇到一个问题 -- 根据数据表结构创建对应的 struct 模型.因为 golang 的使用首字母控制可 ...

  7. postman接口测试工具完整教程

    第一部分:基础篇 postman:4.5.11.安装postman进入postman官网,如果是mac系统可以直接点击mac app安装 如果是windows的话,需要在windows下安装chrom ...

  8. 以太坊系列之十六: 使用golang与智能合约进行交互

    以太坊系列之十六: 使用golang与智能合约进行交互 以太坊系列之十六: 使用golang与智能合约进行交互 此例子的目录结构 token contract 智能合约的golang wrapper ...

  9. Java基础---IO(三)--IO包中的其他类

    第一讲     对象序列化 一.概述 将堆内存中的对象存入硬盘,保留对象中的数据,称之为对象的持久化(或序列化).使用到的两个类:ObjectInputStream和ObjectOutputStrea ...

  10. 打造基于Clang LibTooling的iOS自动打点系统CLAS(三)

    1. 源码变换 第一章我们提到过,CLAS的本质是对源码做一次非常简单的变换(有些文章里称作变形),即Source-Source-Transformation,将打点代码精确地插入到目标函数的首部,保 ...