JAVA UDP网络编程学习笔记

一、UDP网络编程概述

  采用TCP协议通信时,客户端的Socket必须先与服务器建立连接,连接建立成功后,服务器端也会持有客户端连接的Socket,客户端的Socket与服务器端的Socket是对应的,它们构成了两个端点之间的虚拟通信链路。与TCP通信不同,UDP是面向无连接的、不可靠的基于数据包的传输协议。即应用进程(或程序)在使用UDP协议之前,不必先建立连接。自然,发送数据结束时也没有连接需要释放。因此,减少了开销和发送数据之前的延时。UDP也采用端口来区分进程。

  在java中,java.net.DatagramSocket负责接收和发送UDP数据报文,java.net.DatagramPacket表示UDP数据报。每个DatagramSocket与一个数据报套接字(包括本地主机的IP地址和本地UDP端口)绑定,每个DatagramSocket可以把UDP数据报发送给任意一个远程DatagramSocket,也可以接收来自任意一个远程DatagramSocket的数据报。在UDP数据报中包含了目的地址信息,DatagramSocket可以根据该信息把数据报发送的目的地。

  UDP协议是无连接的协议。客户端的DatagramSocket与服务端DatagramSocket不存在一一对应关系,两者无需建立连接,就能交换数据报。每个DatagramSocket对象都会与一个本地端口绑定,在此端口监听发送过来的数据报。在服务器程序中,一般由程序显示地为DatagramSocket指定本地端口。在客户程序中,一般由操作系统为DatagramSocket分配本地端口,这种端口也称为匿名端口。

二、关于DatagramSocket类和DatagramPacket类

  DatagramSocket类的构造方法如下:

  DatagramSocket()throws SocketException

  作用:构造数据报套接字并将其绑定到本地主机上任何可用的端口。套接字将被绑定到INADDR_ANY地址,IP地址由内核来选择。

  DatagramSocket(int port)throws SocketException

  作用:创建数据报套接字并将其绑定到本地主机上的指定端口。套接字将被绑定到INADDR_ANY地址,IP地址由内核来选择。

  DatagramSocket类的常用方法如表所示:

DatagramSocket类的常用方法
void send(DatagramPacket p) throws IOException发送一个UDP数据包。一个UDP数据包就是一个DatagramPacket对象
void receive(DatagramPacket p) throws IOException接收一个UDP数据包。一个UDP数据包就是一个DatagramPacket对象
void connect(InetAddress address,int port)将该UDPSocket变成连接型的UDPSocket
void disconnect()将该UDPSocket变成一个非连接型的UDPSocket
void close()关闭UDPSocket连接

 

 

 

 

 

 

 

  其中,UDPSocket分为“连接型”与“非连接型”两种。默认UDPSocket是“非连接型”的,这个连接不是指向TCP那样进行三步握手,而只是将对方信息与自己关联在一起。

  DatagramPacket类的对象代表了一个UDP数据报包。通过UDP发送数据时,先要根据发送的数据生成一个DatagramPacket对象,然后通过DatagramSocket对象的send()方法发送这个对象。接收时,先要根据要接收数据的缓冲区生成一个Datagrampacket对象,然后通过DatagramPacket对象的receive()方法接收这个对象的数据内容。

  DatagramPacket类的构造方法分为两类:

  一类是创建DatagramPacket对象用来接收数据报包;

  另一类是创建DatagramPacket对象用来发送数据报包。

  它们的区别是,用于发送数据报包的构造方法需要设置数据报包达到的目的地址,若是“连接型”UDP,则不需要设定目的地址,而用于接收数据报包的构造方法无须设定地址。

  用于接收数据报包的构造方法如下:

  DatagramPacket(byte[] buf,int length)

  作用:由接收缓冲区生成一个DatagramPacket对象。buf表示保存传入数据报的缓冲区,length表示要读取的字节数。

  DatagramPacket(byte[] buf,int offset,int length)

  作用:构造DatagramPacket对象。用来接收长度为length的数据包,并在缓冲区中指定了偏移量。

  用于发送数据报包的构造方法如下:

  DatagramPacket(byte[] buf,int length,InetAddress address,int port)

  作用:构造数据报包发送的对象,用来将长度为length的包发送到指定主机上的指定端口号。length参数要小于等于buf的长度。

  DatagramPacket(byte[] buf,int offset,int length,InetAddress address,int port)

  作用:构造数据报包发送的对象,用来将长度为length且偏移量为offset的包发送到指定主机上的指定端口号。length参数要小于等于buf的长度。

DatagramPacket类的常用方法如下表:

DatagramPacket类的常用方法
byte[] getData()返回DatagramPacket对象中包含的数据
int getLength()返回发送/接收数据的长度
int getOffset()返回发送/接收数据在byte[]中的偏移
InetAddress getAddress()返回对方的IP地址。用InetAddress对象表示
int getPort()返回对方的端口号
void setData(byte[] buf,int offset,int length)设置该对象中包含的数据
void setAddress(inetaddress iaddr)设置该对象中包含的IP地址
void setPort()设置该对象中包含的端口号

 

 

 

 

 

 

 

  通过UDP发送/接收数据步骤:

  发送数据,先要根据发送的数据生成一个DatagramPacket对象,并指定发送长度和接收数据的IP地址和端口号,然后通过DatagramSocket对象的send()方法发送这个对象。

  接收数据,根据要接受收数据的缓冲区及大小生成一个DatagramPacket对象,然后通过DatagramSocket对象的receive()方法接收这个对象的数据内容。

三、UDP网络编程练习

  练习代码:

package com.ItHeima.WeekAct;/**服务器**/import java.net.*;public class ChatterClient extends Thread {private DatagramSocket socket;private InetAddress address;private byte[] buf = new byte[1000];private DatagramPacket packet = new DatagramPacket(buf, buf.length);//创建要发送的数据包private int id;//客户端idpublic ChatterClient(int id) {this.id = id;try {socket = new DatagramSocket();//创建UDP套接字address = InetAddress.getByName(null);//取得本地地址} catch (SocketException e) {System.out.println("can not open socket");e.printStackTrace();System.exit(1);} catch (UnknownHostException e) {System.out.println("Can not find host");System.exit(1);}System.out.println("ChatterClient starting");start();//之后调用run()
    }public void run(){try {for(int i = 0 ; i < 25 ; i++){String outMsg = "服务器你好,这是我客户端发过来的数据,请接收!" + id + ",消息" + i;//要发送到服务器的数据socket.send(new DatagramPacket(outMsg.getBytes(),outMsg.getBytes().length, address, ChatterServer.INPORT));//打包数据并将其发送到指定地址+端口的服务端socket.receive(packet);//接收服务端返回的数据包String msg=new String(packet.getData(),packet.getOffset(),packet.getLength());//获取服务器返回的信息String rcvd = "客户端--" + id +", 收到来自服务器的信息" + packet.getAddress() + "," + packet.getPort() + ":" + msg;//组合返回信息System.out.println(rcvd);//输出到控制台
            }} catch (Exception e) {e.printStackTrace();System.exit(1);//出错退出
        }}public static void main(String[] args) {for(int i = 0 ; i < 10 ; i ++ ){new ChatterClient(i);}}
}
package com.ItHeima.WeekAct;/**服务器**/import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class ChatterServer {public static final int INPORT = 1711;//服务器端口private byte[] buf = new byte[1000];private DatagramPacket packet = new DatagramPacket(buf, buf.length);//创建数据包private DatagramSocket socket;//UDP套接字public ChatterServer(){try{socket = new DatagramSocket(INPORT);//启动套接字System.out.println("Server started");while(true){socket.receive(packet);//接收数据包并将当前线程挂起String msg=new String(packet.getData(),packet.getOffset(),packet.getLength());//获取客户端发送的信息String rcvd ="服务器--收到来自客户端的信息:"+ msg+ ", from adddress:" + packet.getAddress() + ",port:" + packet.getPort();//解析数据包System.err.println(rcvd);//打印数据信息String returnMasg = "服务器返回信息:你好客户端,这是你发过来的数据:" + msg+",我将它原样返回";DatagramPacket echo = new DatagramPacket(returnMasg.getBytes(), returnMasg.getBytes().length,packet.getAddress(), packet.getPort());//将接收到包重新包装称UDP数据包准备原封不动的返回给客户端socket.send(echo);//反馈数据包
            }}catch (SocketException e) {System.out.println("Can`t open socket");System.exit(1);}catch (IOException e) {System.out.println("Communication error");e.printStackTrace();}}public static void main(String[] args) {new ChatterServer();//运行服务器
    }
}

  运行结果:

 

转载于:https://www.cnblogs.com/zhishengyong/p/3794749.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/376884.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

firefox 插件开发

IDE&#xff0c;你可以尝试下NetBeans foxbeans这个插件。转载于:https://www.cnblogs.com/sode/archive/2013/01/25/2876562.html

13种负载均衡算法

目录前言&#xff08;1&#xff09;轮转调度&#xff08;Round-Robin Scheduling&#xff09;算法&#xff08;2&#xff09;加权轮转调度&#xff08;Weighted Round-Robin Scheduling&#xff09;算法&#xff08;3&#xff09;随机均衡调度&#xff08;Random Scheduling&am…

对于shell脚本参数获取时的一点小技巧

问题如下&#xff1a; 根据脚本参数的个数$#进行一个循环&#xff0c;在依次输出每个参数$1 $2 $3...... 我有一个循环变量i $i 取到这时的i为1&#xff0c;我想使用这个1再去调用$1,也是就是打印出第一个参数 就是$($i)的意思来取到第几个参数&#xff0c;当然$($i)是不好用的…

(转)页游安全攻与防,SWF加密和隐藏密匙

原文链接&#xff1a;http://netsecurity.51cto.com/art/201211/364775.htm 页游&#xff0c;最最核心的就是客户端&#xff08;swf&#xff09;与服务端的游戏通信了。游戏通信产生的封包&#xff0c;内容是否可识别&#xff0c;可篡改&#xff0c;可重放&#xff0c;处理逻辑…

C++自动类型推导 : auto 与 decltype 用法

基本用法与区别 auto 总是推导出“值类型”&#xff0c;绝不会是“引用”,如果有引用&#xff0c;auto会把引用去掉&#xff0c;推导出值类型&#xff1b; auto 可以附加上 const、volatile、*、& 这样的类型修饰符&#xff0c;得到新的类型。 auto x 10L; // auto推导为…

C++智能指针使用指南 part1:基本使用

加粗样式>TOC 智能指针是代理模式的具体应用&#xff0c;它使用 RAII 技术代理了裸指针&#xff0c;能够自动释放内存&#xff0c; 无需程序员干预&#xff0c;所以被称为“智能指针”。 智能指针不是指针&#xff0c;而是一个对象&#xff0c;所以不要对其调用delete&…

AS3.0 BitmapData类介绍

注&#xff1a;文中的Bitmapdata和BMD均为同一意思BitmapData,BMD为其缩写一&#xff0c;概括&#xff1a; Bitmapdata继承Object对象&#xff0c;实现IBitmapDrawable接口&#xff0c;这个接口有什么用&#xff0c;你可以理解为Drawable,能被画。官方介绍是&#xff1a;IBitma…

C++使用JSON的序列化与反序列化

这里使用的json解析工具为JSON for Modern C,使用的话仅需要包含头文件。 获取方式&#xff1a;wget https://github.com/nlohmann/json/releases/download/v3.7.3/json.hpp JSON json的序列化功能和map一样&#xff0c;用关联数组的"[]"来任意添加数据&#xff0c…

iOS判断为空或者只为空格

本文转载至 &#xff1a;http://www.cnblogs.com/superhappy/archive/2012/11/08/2761403.html 经常有需求 要判断不能为空&#xff0c;后台老是鄙视不做非空判断的前端 &#xff0c;木办法 只能写一个。 第一种想法&#xff1a;我不就是判断 是不是nil就可以了么。结果发现太天…

Hyper-V

Hyper-V&#xff1a;也就是虚拟化技术&#xff0c;允许终端用户在同一台机器上运行多个操作系统&#xff0c;支持32位和64位系统&#xff0c;可以直接在Windows 8上创建自己的虚拟机。开启Hyper-V虚拟机需要更多的内存&#xff0c;正常运行需要至少4GB以上内存&#xff0c;所以…

sdut 1451 括号东东 DP

http://acm.sdut.edu.cn/sdutoj/problem.php?actionshowproblem&problemid1451 题意&#xff1a;中文..... 思路&#xff1a; pku有一道题&#xff0c;经典的括号匹配&#xff08;区间DP&#xff09;题目&#xff0c;那道题目是求的最长满足条件的子串的长度&#xff0c;那…

CDN缓存替代算法

CDN缓存工作过程如下&#xff1a;用户发出一个请求&#xff0c;如果请求被命中&#xff0c;缓存将对用户的请求进行响应&#xff0c;返回其请求的数据&#xff1b;如果未被命中&#xff0c;缓存向上拉取用户需要的数据&#xff0c;并对其存储的数据进行替换。 缓存算法的意义在…

前端开发常用正则表达式

1、电话 var phone /(^[^1][0-9\-]{6,20}$)|(^(134|135|136|137|138|139|150|151|152|157|158|159|182|183|187|188|147|130|131|132|155|156|185|186|145|133|153|180|189|181|184)\d{8}$)/ 2、邮箱 var email /^([a-zA-Z0-9_.-])([a-zA-Z0-9_-])((\.[a-zA-Z0-9_-]{2,3}){1,…

android 中调用接口发送短信

转载&#xff1a;http://ziyu-1.iteye.com/blog/1013932 android中可以通过两种方式发送短信 第一&#xff1a;调用系统短信接口直接发送短信&#xff1b;主要代码如下&#xff1a; Java代码//直接调用短信接口发短信 SmsManager smsManager SmsManager.getDefault(); List…

linux 命令案例学习——文件搜索

两个搜索文件的工具 locate ——仅仅通过文件名查找文件find ——依据文件的各种属性在既定目录&#xff08;包括子目录&#xff09;里查找一个通常与文件搜索命令一起使用、处理搜索结果文件列表的命令 xargs1 locate 1.1 查找文件名中含有zip的文件名 locate zip 看下结…

Redis 缓存击穿、缓存穿透、缓存雪崩的处理方法

常用的分布式缓存Redis单机并发量能达到万级&#xff0c;常用的关系型数据库MySQL一般并发量是千级&#xff0c;他们支持的并发量可能差十倍&#xff0c;所以要尽可能把流量拦截在缓存层。 缓存击穿 一个并发访问量比较大的key在某个时间过期&#xff0c;导致所有的请求直接打…

Java-- 异常与记录日志

可以使用java.util.logging工具将输出记录在日志中。记录日志的的功能还是很简单的&#xff0c;下面直接铺出代码&#xff1a; 1 package com.exceptions;2 3 import java.io.*;4 import java.util.logging.Logger;5 6 class LoggingException extends Exception{7 private…

图像处理基础

图像处理基础 在计算机中&#xff0c;按照颜色和灰度的多少可以将图像分为二值图像、灰度图像、索引图像和真彩色RGB图像四种基本类型。目前&#xff0c;大多数图像处理软件都支持这四种类型的图像。 (1) 二值图像&#xff1a;一幅二值图像的二维矩阵仅由0、1两个值构成&#x…

缓存一致性解决方法

对于缓存 数据库读写&#xff0c;有个经典的Cache Aside Pattern&#xff1a; 读取&#xff1a;先读取缓存&#xff0c;缓存里没有&#xff0c;读取数据库&#xff0c;然后返回响应&#xff0c;顺便保存缓存&#xff1a; 更新&#xff1a;先更新数据库&#xff0c;然后删除缓…

使用SpringMVC的表单验证

上一篇搭建了基本项目&#xff0c;这一篇在此基础上加入表单验证功能。 第一步&#xff0c;添加command类 Java代码 package test.bean; import javax.validation.constraints.Size; public class User { Size(min3,max30) private String username; …