Beginning with version 1.7.0 socat provides means to freely control
important aspects of socket handling. This allows to experiment with socket
types and protocols that are not explicitely implemented in socat.
从版本 1.7.0 开始,socat 提供了自由控制套接字处理的重要方面的手段。这允许尝试在 socat 中未明确实现的套接字类型和协议。
The related socat features fall into three major categories:
相关的 socat 功能分为三大类:
In practice this gives you two possibilities:
实际上,这给您两种可能性:
If you want to cope with sockets staying within the usual domains ( =
protocol families = address families) which are IPv4, IPv6, UNIX/local, and
raw interface for socat 1.7.0, it is sufficient to learn about a couple of
address options that allow to change default
parameters, and to apply generic socket options.
如果您想处理套接字保持在通常的域内(=协议族=地址族),这些域包括 IPv4、IPv6、UNIX/local 和 socat 1.7.0 的原始接口,只需了解一些地址选项即可,这些选项允许更改默认参数,并应用通用套接字选项。
For other address families socat provides generic socket addresses.
对于其他地址族,socat 提供通用套接字地址。
A relatively new communication protocol has been introduced in the Internet
community for which no socat address type has been implemented up to version
1.7.0
(see IETF's
Datagram Congestion Control Protocol
and Linux
foundation Net:DCCP for more info). Taken that the
operating system implements DCCP, it is possible to use this protocol
with socat while just employing standard socket addresses and some options.
一个相对较新的通信协议已经引入互联网社区,截至版本 1.7.0,尚未实现任何 socat 地址类型(请参阅 IETF 的 Datagram Congestion Control Protocol 和 Linux 基金会的 Net:DCCP 了解更多信息)。假设操作系统实现了 DCCP,可以在 socat 中使用此协议,只需使用标准套接字地址和一些选项。
A simple server that accepts a DCCP connection, passes the arriving data to a
subprocess for converting upper case to lower case characters, and then
returns it to the client:
一个简单的服务器接受 DCCP 连接,将到达的数据传递给子进程以将大写字符转换为小写字符,然后将其返回给客户端:
A simple client that sends some upper case characters to the server via DCCP
and prints what the server returns:
一个简单的客户端,通过 DCCP 将一些大写字符发送到服务器,并打印服务器返回的内容:
We choose the TCP4 addresses as base because it best matches the DCCP
requirements:
我们选择 TCP4 地址作为基础,因为它最符合 DCCP 的要求:
Option type=6 changes TCP's
SOCK_STREAM parameter to SOCK_DCCP, and
prototype=33 replaces the
default IPPROTO_TCP with IPPROTO_DCCP.
选项 type=6 将 TCP 的 SOCK_STREAM 参数更改为 SOCK_DCCP ,而
prototype=33 将默认的 IPPROTO_TCP 替换为 IPPROTO_DCCP 。
DCCP has an important parameter, the service code. It provides another
multiplexing layer beyond the protocol ports. The Linux implementation of DCCP
allows to set this parameter with code like setsocktopt(fd, SOL_DCCP,
DCCP_SOCKOPT_SERVICE, {1}, sizeof(int)). The equivalent generic socat
option is: setsockopt-int=269:2:1 for service code 1.
If the service codes on server and client do not match the connect()
operation fails with error:
DCCP 有一个重要的参数,即服务代码。它提供了协议端口之外的另一个多路复用层。DCCP 的 Linux 实现允许使用类似 setsocktopt(fd, SOL_DCCP,
DCCP_SOCKOPT_SERVICE, {1}, sizeof(int)) 的代码设置此参数。等效的通用 socat 选项是: setsockopt-int=269:2:1 用于服务代码 1。如果服务器和客户端上的服务代码不匹配,则 connect() 操作将因错误而失败:
... E connect(3, AF=2 127.0.0.1:4096, 16): Invalid request code |
Please note that this examples works with IPv6 as well, you just need to
replace the TCP4 words with TCP6, and the IPv4 socket address with an
appropriate IPv6 socket address, e.g. [::1]!
请注意,这些示例也适用于 IPv6,您只需将 TCP4 更改为 TCP6,并将 IPv4 套接字地址更改为适当的 IPv6 套接字地址,例如 [::1] !
socat's generic socket addresses are a more comprehensive mechanism that
allows to deal with protocol families whose socket addresses are not supported
by socat - no semantical parsing, no structured assignment to the struct
components are available. Instead, the socket address records for binding and
connecting/sending are specified in unstructured hexadecimal form. The
following example demonstrates this by performing simple data transfer over
raw AppleTalk protocol.
socat 的通用套接字地址是一种更全面的机制,允许处理协议族的套接字地址不受 socat 支持的情况 - 没有语义解析,也没有将结构化分配给结构组件。相反,用于绑定和连接/发送的套接字地址记录以非结构化十六进制形式指定。以下示例通过在原始 AppleTalk 协议上执行简单数据传输来演示这一点。
Note: I do not have any knowledge about AppleTalk. I just managed to
configure my Linux host to tolerate the creation of a receiving and a sending
socket. Don't blame me nor ask me for support if it does not work for you.
注意:我对 AppleTalk 一无所知。我只是设法配置我的 Linux 主机以容忍创建一个接收套接字和一个发送套接字。如果对您不起作用,请不要责怪我,也不要向我寻求支持。
Install the netatalk package. Check that /etc/netatalk/atalkd.conf
has an entry like eth0 -phase 2 -net 0-65534 -addr 65280.243. The
last part is an arbitrary (?) host address, some of the following values must
fit it. Make sure the atalkd daemon is running. Run the AppleTalk
ping command:
安装 netatalk 包。检查 /etc/netatalk/atalkd.conf 是否有类似 eth0 -phase 2 -net 0-65534 -addr 65280.243 的条目。最后一部分是一个任意的主机地址,一些以下值必须匹配它。确保 atalkd 守护程序正在运行。运行 AppleTalk ping 命令:
If you get an error like:
如果您遇到类似错误:
Device or resource busy |
then try to restart atalkd:
然后尝试重新启动 atalkd :
When aecho works like ping you are ready for the next step.
当 aecho 的工作方式类似于 ping 时,您已准备好进行下一步。
We start a socat process with a receiver and echo service:
我们启动一个带有接收器和回显服务的 socat 进程:
Then, in another shell on the same host, we start a client socket process
that sends data to the server and gets the answer:
然后,在同一台主机上的另一个 shell 中,我们启动一个客户端套接字进程,向服务器发送数据并获取答复:
The client process should print the data.
客户端进程应打印数据。
How did this work? The generic socat address has just used the system call
parameters that were provided on command line, without knowing anything about
AppleTalk sockets and protocol. The values 5, 2, and 0 are directly used for
the socket() call: they specify the domain (PF_APPLETALK=5),
socket type (SOCK_DGRAM=2), and no protocol (0) - values for Linux.
The long hex strings define the socket addresses. They can only be constructed
with knowledge of the underlying structure. In
/usr/include/linux/atalk.h we find the following declarations:
这是如何工作的?通用的 socat 地址只是使用了在命令行上提供的系统调用参数,而不知道任何关于 AppleTalk sockets 和协议的信息。值 5、2 和 0 直接用于 socket() 调用:它们指定了域( PF_APPLETALK=5 )、套接字类型( SOCK_DGRAM=2 )和无协议(0)- 适用于 Linux 的值。长十六进制字符串定义了套接字地址。只有了解底层结构才能构建它们。在 /usr/include/linux/atalk.h 中,我们找到以下声明:
struct atalk_addr { __be16 s_net; __u8 s_node; }; struct sockaddr_at { sa_family_t sat_family; __u8 sat_port; struct atalk_addr sat_addr; char sat_zero[8];
After rolling out atalk_addr and considering implicit padding by the
C programming language we get the following byte map:
在推出 atalk_addr 并考虑 C 编程语言的隐式填充后,我们得到以下字节映射:
component | offset | length | value | meaning |
---|---|---|---|---|
sat_family | 0 | 2 | x0005 | address family 地址族 |
sat_port | 2 | 1 | x40 | port |
- | 3 | 1 | x00 | padding |
sat_addr.s_net | 4 | 2 | xff00 | network address 网络地址 |
sat_addr.s_node | 6 | 1 | xf3 | node address 节点地址 |
- | 7 | 1 | x00 | padding |
sat_zero | 8 | 8 | x0000000000000000 | padding |
Note that hexadecimal ff00 is the same as decimal 65280, and hexadecimal xf3
is the same as decimal 243 - these are the numbers specified in
atalkd.conf.
请注意,十六进制 ff00 等同于十进制 65280,十六进制 xf3 等同于十进制 243 - 这些是在 atalkd.conf 中指定的数字。
The address family component must be omitted from the socket address because
it is added by socat implicitely. The resulting hexadecimal representation of
the target socket address is therefore:
由于 socat 隐式添加了地址族组件,因此必须从套接字地址中省略地址族组件。因此,目标套接字地址的十六进制表示如下:
The receiver just has to specify the port, so its bind address data is:
接收方只需指定端口,因此其绑定地址数据为:
Finding the correct parameters and socket addresses is not always trivial.
Therefore this section provides tables with the parameters of common socket
types. Some of these types are directly implemented by socat (and other
programs). Establishing interoperability between a directly implemented
socket and a generic socket might be your first step before entering unknown
ground.
找到正确的参数和套接字地址并不总是简单的。因此,本节提供了常见套接字类型参数的表格。其中一些类型是由 socat(和其他程序)直接实现的。在进入未知领域之前,建立直接实现套接字和通用套接字之间的互操作性可能是您的第一步。
name | domain | socktype | protocol | level | remark | |
---|---|---|---|---|---|---|
UDP4 | PF_INET | SOCK_DGRAM | IPPROTO_UDP | SOL_UDP | ||
UDP6 | PF_INET6 | SOCK_DGRAM | IPPROTO_UDP | SOL_UDP | ||
raw IPv4 原始 IPv4 | PF_INET | SOCK_RAW | IPPROTO_RAW | SOL_IP | ||
raw IPv6 原始 IPv6 | PF_INET6 | SOCK_RAW | IPPROTO_RAW | SOL_IPV6 | ||
UNIX | PF_LOCAL | SOCK_DGRAM | 0 | SOL_SOCKET | ||
PACKET | PF_PACKET | SOCK_RAW | 768 | SOL_PACKET | tcpdump (include layer 2 header) tcpdump(包括第二层标头) | |
PACKET | PF_PACKET | SOCK_DGRAM | 768 | SOL_PACKET | no level 2 header 没有第二层标头 | |
SCTP4 | PF_INET | SOCK_SEQPACKET | IPPROTO_SCTP | SOL_SCTP |
name | Linux | FreeBSD | NetBSD | OpenBSD | Solaris | AIX | Cygwin | Mac OS X | HP-UX |
---|---|---|---|---|---|---|---|---|---|
PF_LOCAL | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
PF_INET | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
PF_APPLETALK | 5 | 16 | 16 | 16 | 16 | 16 | 16 | 16 | 16 |
PF_INET6 | 10 | 28 | 24 | 24 | 26 | 24 | - | 30 | 22 |
PF_PACKET | 17 | - | - | - | - | - | - | - | - |
SOCK_STREAM | 1 | 1 | 1 | 1 | 2 | 1 | 1 | 1 | 1 |
SOCK_DGRAM | 2 | 2 | 2 | 2 | 1 | 2 | 2 | 2 | 2 |
SOCK_RAW | 3 | 3 | 3 | 3 | 4 | 3 | 3 | 3 | 3 |
SOCK_SEQPACKET | 5 | 5 | 5 | 5 | 6 | 5 | 5 | 5 | 5 |
SOCK_DCCP | (6) | - | - | - | - | - | - | - | - |
SOCK_PACKET | 10 | - | - | - | - | - | - | - | - |
IPPROTO_IP | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
IPPROTO_TCP | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
IPPROTO_UDP | 17 | 17 | 17 | 17 | 17 | 17 | 17 | 17 | 17 |
IPPROTO_DCCP | 33 | - | - | - | - | - | - | - | - |
IPPROTO_SCTP | 132 | 132 | - | - | 132 | 132 | - | - | - |
IPPROTO_RAW | 255 | 255 | 255 | 255 | 255 | - | - | - | - |
SOL_SOCKET | 1 | 65535 | 65535 | 65535 | 65535 | 65535 | 65535 | 65535 | 65535 |
SOL_IP | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
SOL_TCP | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
SOL_UDP | 17 | - | - | - | - | - | 17 | - | - |
SOL_IPV6 | 41 | 41 | 41 | 41 | 41 | 41 | - | 41 | 41 |
SOL_PACKET | 263 | - | - | - | - | - | - | - | - |
SOL_DCCP | 269 | - | - | - | - | - | - | - | - |
These hexadecimal data define socket addresses for local and remote sockets,
and for bind and range options. The basis is the struct sockaddr_* for
the respective address family that should be declared in the C include files.
Please keep in mind that their first two bytes (sa_family and - on BSD
- sa_len) are implicitely prepended by socat.
这些十六进制数据定义了本地和远程套接字的套接字地址,以及绑定和范围选项。基础是应在 C 包含文件中声明的相应地址族的 struct sockaddr_* 。请记住,它们的前两个字节( sa_family 和 - 在 BSD 上 - sa_len )会被 socat 隐式地添加在前面。
name | socket address type (without leading address family) 套接字地址类型(不包括前导地址族) | binary specification 二进制规范 |
---|---|---|
IPv4 | 2 bytes port, 4 bytes IPv4 addr, 8 bytes 0 2 字节端口,4 字节 IPv4 地址,8 字节 0 | x0016 x7f000001 x0000000000000000 |
IPv6 | 2 bytes port, 4 bytes flowinfo, 16 bytes IPv6 addr, 4 bytes scope-id 2 字节端口,4 字节流信息,16 字节 IPv6 地址,4 字节范围 ID | x0016 x00000000 x0102030405060708090a0b0c0d0e0f x00000000 |
UNIX | variable length path name, 0 terminated 可变长度路径名,以 0 结尾 | x2f746d702f736f636b00 |
PACKET | 2 bytes protocol (0x0003), interface index as int in host byte order, 8 bytes 0 2 字节协议(0x0003),接口索引作为主机字节顺序中的整数,8 字节 0 | x0003 x02000000 x0000000000000000 |
For AppleTalk see above example.
对于 AppleTalk,请参见上面的示例。
name | socket address type (without leading address family) 套接字地址类型(不包括前导地址族) | binary specification 二进制规范 |
---|---|---|
IPv6 | 2 bytes port, 4 bytes flowinfo, 16 bytes IPv6 addr, 4
bytes scope-id, 4 bytes src-id 2 字节端口,4 字节流信息,16 字节 IPv6 地址,4 字节范围 ID,4 字节源 ID | x0016 x00000000 x0102030405060708090a0b0c0d0e0f x00000000 x00000000 |
Eager to experiment with exotic socket types? Run nmap's protocol scan and
see what is available on your system:
渴望尝试异国情调的套接字类型?运行 nmap 的协议扫描,看看您的系统上有什么可用的:
Copyright: Gerhard Rieger 2008
版权所有:Gerhard Rieger 2008
License: GNU Free Documentation License (FDL)
许可证:GNU 自由文档许可证(FDL)