【计算机网络】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连接发送数据,让对方紧急处理。

相关推荐
鱼骨不是鱼翅33 分钟前
网络层协议-----IP协议
网络·网络协议·tcp/ip
API开发1 小时前
APISQL在线一键安装教程
服务器·api
LLLuckyGirl~1 小时前
计算机网络之---无线通信概述
网络·计算机网络
车到山前必有路5292 小时前
计算机网络(四)——网络层
计算机网络
王鹏程@1233 小时前
mysql 双主双从 + proxysql 代理
运维·服务器
地衣君3 小时前
服务器一次性部署One API + ChatGPT-Next-Web
服务器·前端·chatgpt·aigc·oneapi
几维安全3 小时前
如何通过移动应用安全分析量化您的网络安全投资回报?
网络·安全·web安全
小丁爱养花4 小时前
网络协议(八):IP 协议
开发语言·网络·网络协议·tcp/ip
hgdlip4 小时前
ip属地是根据手机号还是位置
网络·tcp/ip·web安全·手机号