【计算机网络】Socket的OOBInline选项与UrgentData

Socket的OOBINLINE选项是用于处理TCP紧急数据的一个设置。TCP紧急数据通常指的是那些需要优先处理的数据,例如某些控制信息或关键数据。

OOB(Out-of-Band)表示带外数据,OOBInline是一个Socket选项,用于控制是否将接收到的带外数据(Out-of-Band data)与普通数据混合在一起。如果设置了OOBInline为true,那么带外数据将与普通数据混合在一起,可以通过相应的方式进行处理。如果设置为false,则带外数据将单独处理。默认情况下,OOBInline为false。

当OOBINLINE选项被设置为true时,表示支持发送一个字节的TCP紧急数据。这可以通过Socket类的sendUrgentData(int data)方法来实现。在这种情况下,接收方会把接收到的紧急数据与普通数据放在同样的队列中,从而可以通过套接字输入流来接收这些紧急数据。

然而,如果OOBINLINE选项被设置为false(这是其默认值),那么当接收方收到紧急数据时,它不会进行任何特殊处理,而是直接将其丢弃。这意味着,如果用户希望接收紧急数据,他们必须显式地将OOBINLINE选项设置为true。

总的来说,OOBINLINE选项为Socket提供了一种处理紧急数据的机制,允许开发者根据实际需求来选择是否接收和如何处理这些紧急数据。

在JAVA中可以通过下面的api来开启OOBINLINE:

java 复制代码
public void setOOBInline(boolean on) throws SocketException

如果这个Socket的OOBINLINE选项打开,可以通过Socket类的sendUrgentData方法向服务器发送一个单字节的数据。这个单字节数据并不经过输出缓冲区,而是立即发出。虽然在客户端并不是使用OutputStream向服务器发送数据,但在服务端程序中这个单字节的数据是和其它的普通数据混在一起的。因此,在服务端程序中并不知道由客户端发过来的数据是由OutputStream还是由sendUrgentData发过来的。

下面是sendUrgentData方法的声明:

java 复制代码
public void sendUrgentData(int data) throws IOException

虽然sendUrgentData的参数data是int类型,但只有这个int类型的低字节被发送,其它的三个字节被忽略。

下面的代码演示了如何使用SO_OOBINLINE选项来发送单字节紧急数据。

Socket服务端代码如下:

java 复制代码
package com.morris.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Socket服务端,演示OOBInline选项的效果
 */
public class OobInlineServerDemo {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8899);
        System.out.println("server is listening at 8899");
        while (true) {
            Socket socket = serverSocket.accept();
            // 允许带外数据(Out-of-Band data)与普通数据混合在一起
//            socket.setOOBInline(true);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line;
            while (null != (line = bufferedReader.readLine())) {
                System.out.println(line);
            }
            socket.close();
        }
    }
}

Socket客户端代码如下:

java 复制代码
package com.morris.socket;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;

/**
 * Socket客户端,演示OOBInline选项的效果
 */
public class OobInlineClientDemo {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 8899);
        PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
        printWriter.write('C'); // 向服务器发送字符"C"
        printWriter.write("hello world");
        // 客户端发送紧急数据
        socket.sendUrgentData(65); // 向服务器发送字符"A"
        socket.sendUrgentData(322); // 向服务器发送字符"B"
        printWriter.flush();
        socket.close();
    }
}

先运行服务端再运行客户端,服务端收到的数据如下:

shell 复制代码
server is listening at 8899
ABChello world

从接收到的数据可以发现一个问题,在客户端中先后向服务器发送了Chello worldAB。而在服务端接收到的数据顺序是ABChello world。这种现象说明使用sendUrgentData方法发送数据后,系统会立即将这些数据发送出去;而使用write发送数据,必须要使用flush方法才会真正发送数据。

服务端tcpdump抓到的包如下:

shell 复制代码
11:32:46.153914 IP 127.0.0.1.42752 > 127.0.0.1.8899: Flags [P.U], seq 1:2, ack 1, win 512, urg 1, options [nop,nop,TS val 532795477 ecr 532795476], length 1
11:32:46.153977 IP 127.0.0.1.42752 > 127.0.0.1.8899: Flags [P.U], seq 2:3, ack 1, win 512, urg 1, options [nop,nop,TS val 532795477 ecr 532795477], length 1

可见包中的标志位有U。

然后将服务端下面的代码注释掉,关闭OOBInline选项:

java 复制代码
//            socket.setOOBInline(true);

先运行服务端再运行客户端,服务端收到的数据如下:

shell 复制代码
server is listening at 8899
Chello world

可以看到服务端只收到了普通数据,收不到紧急数据了。

TCP的紧急指针,一般都不建议使用,而且不同的TCP/IP实现,也不同,一般说如果你有紧急数据宁愿再建立一个新的TCP/IP连接发送数据,让对方紧急处理。

相关推荐
starfire_hit1 小时前
JAVAWEB根据前台请求获取用户IP
java·服务器·网络
Java后端的Ai之路2 小时前
【Python 教程14】- 网络编程
网络·python·php
learning-striving2 小时前
kali连不上网解决方法
linux·开发语言·网络·php·kali
云边有个稻草人2 小时前
打工人摸鱼新姿势!轻量斗地主服务器,内网穿透让同事远程联机不翻车
运维·服务器·cpolar
阿钱真强道2 小时前
12 JetLinks MQTT直连设备事件上报实战(继电器场景)
linux·服务器·网络·数据库·网络协议
九.九2 小时前
CANN HCOMM 底层机制深度解析:集合通信算法实现、RoCE 网络协议栈优化与多级同步原语
网络·网络协议·算法
wbs_scy2 小时前
Linux 进阶指令实操指南:文件查看、时间管理、搜索压缩全场景覆盖(附高频案例)
linux·运维·服务器
安科瑞刘鸿鹏172 小时前
高速路灯故障难定位?用 ASL600 实现精确单灯监测与维护预警
运维·网络·物联网·安全
Lethehong2 小时前
实测可用|一文搞定OpenClaw部署,免费kimi-k2.5+飞书远程,新手也能秒上手
linux·运维·服务器·玩转openclaw·云端创意实践
逍遥德2 小时前
Sring事务详解之02.如何使用编程式事务?
java·服务器·数据库·后端·sql·spring