JAVA UPD通信:ADSL拨号,外网给内网发包能收到,内网给外网回包收不到

JAVA UPD通信:ADSL拨号,外网给内网发包能收到,内网给外网回包收不到,第1张

手机的gprs的IP地址不是公网IP。

你的服务器发回消息抵达不了手机。

你回复消息的时间和手机发送消息的时间如果间隔太长,就发不到了

如果时间很短,应该是可以的

具体时间要看运营商的设置,还有当时网络繁忙的程度

你说的还不清楚。Java网络编程使用Socket,同为一个网络下的主机时是肯定没问题的,不论同一局域网或广域网。如果内网跨越网关,我没做过试验,按我的理解,内网主机做客户端,独立主机做服务器应该可行,反之不行。

Socket套接字,是由系统提供用于网络通信的技术( *** 作系统给应用程序提供的一组API叫做Socket API),是基于TCP/IP协议的网络通信的基本 *** 作单元。基于Socket套接字的网络程序开发就是网络编程。

socket可以视为是应用层和传输层之间的通信桥梁;

传输层的核心协议有两种:TCP,UDP;socket API也有对应的两组,由于TCP和UDP协议差别很大,因此,这两组API差别也挺大。

分类:

Socket套接字主要针对传输层协议划分为如下三类:

流套接字:使用传输层TCP协议

TCP,即Transmission Control Protocol(传输控制协议),传输层协议;

TCP的特点:

有连接:像打电话,得先接通,才能交互数据

可靠传输:传输过程中,发送方知道接收方有没有收到数据(打电话就是可靠传输);

面向字节流:以字节为单位进行传输(非常类似于文件 *** 作中的字节流);

全双工:一条链路,双向通信;

有接收缓冲区,也有发送缓冲区。

大小不限

对于字节流来说,可以简单的理解为,传输数据是基于IO流,流式数据的特征就是在IO流没有关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收。

数据报套接字:使用传输层UDP协议

UDP,即User Datagram Protocol(用户数据报协议),传输层协议。

UDP的特点:

无连接:像发微信,不需要接通,直接就能发数据;

不可靠传输:传输过程中,发送方不知道接收方有没有收到数据(发微信就是不可靠传输);

面向数据报:以数据报为单位进行传输(一个数据报都会明确大小)一次发送/接收必须是一个完整的数据报,不能是半个,也不能是一个半;

全双工:一条链路,双向通信;

有接收缓冲区,无发送缓冲区;

大小受限:一次最多传输64k;

对于数据报来说,可以简单的理解为,传输数据是一块一块的,发送一块数据假如100个字节,必须一次发送,接收也必须一次接收100个字节,而不能分100次,每次接收1个字节。

原始套接字

原始套接字用于自定义传输层协议,用于读写内核没有处理的IP协议数据。

二、UDP数据报套接字编程

UDPSocket中,主要涉及到两类:DatagramSocket、DatagramPacket;

DatagramSocket API

DatagramSocket 创建了一个UDP版本的Socket对象,用于发送和接收UDP数据报,代表着 *** 作系统中的一个socket文件,( *** 作系统实现的功能–>)代表着网卡硬件设备的抽象体现。

DatagramSocket 构造方法:

方法签名 方法说明

DatagramSocket() 创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口(一般用于客户端)

DatagramSocket(int port) 创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用于服务端)

DatagramSocket 方法:

方法签名 方法说明

void receive(DatagramPacket p) 从此套接字接收数据报(如果没有接收到数据报,该方法会阻塞等待)

void send(DatagramPacket p) 从此套接字发送数据报包(不会阻塞等待,直接发送)

void close() 关闭此数据报套接字

DatagramPacket API

代表了一个UDP数据报,是UDP Socket发送和接收的数据报,每次发送/接收数据报,都是在传输一个DatagramPacket对象。

DatagramPacket 构造方法:

方法签名 方法说明

DatagramPacket(byte[] buf, int length) 构造一个DatagramPacket以用来接收数据报,接收的数据保存在字节数组(第一个参数buf)中,接收指定长度(第二个参数length)

DatagramPacket(byte[] buf, int offset, int length,SocketAddress address) 构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组(第一个参数buf)中,从0到指定长度(第二个参数length)。address指定目的主机的IP和端口号

DatagramPacket 方法:

方法签名 方法说明

InetAddress getAddress() 从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址

int getPort() 从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端主机端口号

byte[] getData() 获取数据报中的数据

构造UDP发送的数据报时,需要传入 SocketAddress ,该对象可以使用 InetSocketAddress 来创建。

InetSocketAddress API

InetSocketAddress ( SocketAddress 的子类 )构造方法:

方法签名 方法说明

InetSocketAddress(InetAddress addr, int port) 创建一个Socket地址,包含IP地址和端口号

示例1:写一个简单的客户端服务程序,回显服务(EchoSever)

在这里插入描述

构建Socket对象有很多失败的可能:

端口号已经被占用,同一个主机的两个程序不能有相同的端口号(这就好比两个人不能拥有相同的电话号码);

此处,多个进程不能绑定同一个端口号,但是一个进程可以绑定多个端口,(这就好比一个人可以拥有多个手机号),一个进程可以创建多个Socket对象,每个Socket都绑定自己的端口。

每个进程能够打开的文件个数是有上限的,如果进程之间已经打开了很多文件,就可能导致此时的Socket文件不能顺利打开;

在这里插入描述

这个长度不一定是1024,假设这里的UDP数据最长是1024,实际的数据可能不够1024

在这里插入描述

这里的参数不再是一个空的字节数组了,response是刚才根据请求计算的得到的响应,是非空的,DatagramPacket 里面的数据就是String response的数据。

responsegetBytes()length:这里拿到的是字节数组的长度(字节的个数),而responselength得到的是字符的长度。

五元组

一次通信是由5个核心信息描述的:源IP、 源端口、 目的IP、 目的端口、 协议类型。

站在客户端角度:

源IP:本机IP;

源端口:系统分配的端口;

目的IP:服务器的IP;

目的端口:服务器的端口;

协议类型:TCP;

站在服务器的角度:

源IP:服务器程序本机的IP;

源端口:服务器绑定的端口(此处手动指定了9090);

目的IP:包含在收到的数据报中(客户端的IP);

目的端口:包含在收到的数据报中(客户端的端口);

协议类型:UDP;

在Java中 *** 纵UDP

使用位于JDK中Javanet包下的DatagramSocket和DatagramPacket类,可以非常方便地控制用户数据报文。

在描述它们之前,必须了解位于同一个位置的InetAddress类。InetAddress实现了Javaio Serializable接口,不允许继承。它用于描述和包装一个Internet IP地址,通过三个方法返回InetAddress实例:

getLocalhost():返回封装本地地址的实例。

getAllByName(String host):返回封装Host地址的InetAddress实例数组。

getByName(String host):返回一个封装Host地址的实例。其中,Host可以是域名或者是一个合法的IP地址。

DatagramSocket类用于创建接收和发送UDP的Socket实例。和Socket类依赖SocketImpl类一样,DatagramSocket类的实现也依靠专门为它设计的DatagramScoketImplFactory类。DatagramSocket类有3个构建器:

DatagramSocket():创建实例。这是个比较特殊的用法,通常用于客户端编程,它并没有特定监听的端口,仅仅使用一个临时的。

DatagramSocket(int port):创建实例,并固定监听Port端口的报文。

DatagramSocket(int port, InetAddress localAddr):这是个非常有用的构建器,当一台机器拥有多于一个IP地址的时候,由它创建的实例仅仅接收来自LocalAddr的报文。

值得注意的是,在创建DatagramSocket类实例时,如果端口已经被使用,会产生一个SocketException的异常抛出,并导致程序非法终止,这个异常应该注意捕获。DatagramSocket类最主要的方法有4个:

Receive(DatagramPacket d):接收数据报文到d中。receive方法产生一个“阻塞”。

Send(DatagramPacket d):发送报文d到目的地。

SetSoTimeout(int timeout):设置超时时间,单位为毫秒。

Close():关闭DatagramSocket。在应用程序退出的 焙颍�ǔ;嶂鞫�头抛试矗�乇誗ocket,但是由于异常地退出可能造成资源无法回收。所以,应该在程序完成时,主动使用此方法关闭Socket,或在捕获到异常抛出后关闭Socket。

“阻塞”是一个专业名词,它会产生一个内部循环,使程序暂停在这个地方,直到一个条件触发。

DatagramPacket类用于处理报文,它将Byte数组、目标地址、目标端口等数据包装成报文或者将报文拆卸成Byte数组。应用程序在产生数据包是应该注意,TCP/IP规定数据报文大小最多包含65507个,通常主机接收548个字节,但大多数平台能够支持8192字节大小的报文。DatagramPacket类的构建器共有4个:

DatagramPacket(byte[] buf, int length, InetAddress addr, int port):从Buf数组中,取出Length长的数据创建数据包对象,目标是Addr地址,Port端口。

DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port):从Buf数组中,取出Offset开始的、Length长的数据创建数据包对象,目标是Addr地址,Port端口。

DatagramPacket(byte[] buf, int offset, int length):将数据包中从Offset开始、Length长的数据装进Buf数组。

DatagramPacket(byte[] buf, int length):将数据包中Length长的数据装进Buf数组。

DatagramPacket类最重要的方法就是getData()了,它从实例中取得报文的Byte数组编码。

TCP是面向连接,UDP面向非连接,资料不复制,在这里简单说下:\x0d\TCP建立连接时需要传说的三次握手,服务端与客户端需要确认对方身份而已,建立好连接后,就开始传递消息,直到有一方断开连接位置。 就好比两个人打电话,要先通了才能说话。\x0d\UDP只是数据报发送,它的优点速度快,并非要向TCP那样麻烦建立,它只负责将信息发出,但是并不确保信息的准确完整性等,就好比发短信,短信是出去了,但是中间是否有问题,是否对方手机能收到就不管了。\x0d\在java中想要实现上述两种协议通信,可采用socket建立连接,socket可以理解为码头,其实是套接字,这里简单说下,就好比两个城市运输货物,通过码头走货一样。至于如何通过socket建立两个连接,网上资料多的是,在这里不复制例子了。

以上就是关于JAVA UPD通信:ADSL拨号,外网给内网发包能收到,内网给外网回包收不到全部的内容,包括:JAVA UPD通信:ADSL拨号,外网给内网发包能收到,内网给外网回包收不到、JAVA用udp从本地网络穿透到公网之后,从其他网络作为客户端发送udp包到服务器正常接收。、在javasocket网络编程中,开发基于udp协议的程序使用的套接字有哪些等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9691283.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-01
下一篇2023-05-01

发表评论

登录后才能评论

评论列表(0条)

    保存