1.如果我将该套接字绑定到一个端口并监听该端口,那么在这两个调用之前分叉的套接字也会监听并绑定到同一个端口吗?
一旦您有了文件描述符(由socket 或accept 创建),对该文件描述符的更改就会反映在所有进程中该描述符的克隆中。
由于您不能两次绑定套接字,因此可以使用以下内容来验证我的声明。 (它是用 Perl 编写的,但是 C 程序员应该可以毫无问题地读取它。die 抛出异常,$! 是 strerror(errno),$!{EINVAL} 相当于 errno == EINVAL。)
#!/usr/bin/perl
use 5.014;
use warnings;
use Socket qw( pack_sockaddr_in AF_INET SOCK_STREAM INADDR_ANY SOMAXCONN );
socket(my $socket, AF_INET, SOCK_STREAM, 0)
or die("socket: $!\n");
defined( my $pid = fork() )
or die("fork: $!\n");
if (!$pid) {
bind($socket, pack_sockaddr_in(0, INADDR_ANY))
or die("bind: $!\n");
listen($socket, SOMAXCONN)
or die("listen: $!\n");
exit;
}
waitpid($pid, 0) > 0
or die("waitpid: $!\n");
if (bind($socket, pack_sockaddr_in(0, INADDR_ANY))) {
say "Socket bound again. bind doesn't transcend processes.";
} else {
if ($!{EINVAL}) {
say "Socket already bound. bind transcends processes.";
} else {
die("bind in parent: $!\n");
}
}
输出:
Socket already bound. bind transcends processes.
2.如果我在套接字上使用接受并且套接字接受连接并链接到客户端套接字:分叉的套接字也会连接到该客户端套接字吗?
没有。这个问题的前提是accept 创建的套接字和调用accept 的套接字之间存在链接/连接,但没有任何这样的链接/连接(在任何进程中)。
3.我可以使用为 TCP 连接打开的套接字作为 TCP 接收方和 UDP 发送方吗?
4.我可以使用为 TCP 连接打开的套接字作为 UDP 接收方和 TCP 发送方吗?
没有。套接字是 TCP 套接字或 UDP 套接字。您不能通过 TCP 套接字发送/接收 UDP 数据包,也不能通过 UDP 套接字发送/接收 TCP 数据包。甚至没有办法尝试。
但是,TCP 和 UDP 端口是独立的,因此您可以同时使用 TCP 端口 1234 和 UDP 端口 1234(使用两个不同的套接字)。
5.如果我有一个为 TCP 连接打开的套接字:我可以使用带有最后 2 个参数 NULL 的 sendto 没有任何问题吗?
是的。 send 可以在 TCP 套接字上调用,send 是根据 sendto 定义的,最后两个参数是 NULL 和 0。
根据我的(GNU/Linux)系统上的man 2 send:
send(sockfd, buf, len, flags); 等价于sendto(sockfd, buf, len, flags, NULL, 0);
实际上,您必须使用 TCP 套接字将最后两个参数设置为 NULL 和 0。
根据我的 (GNU/Linux) 系统上的man 2 sendto:
如果在连接模式(SOCK_STREAM、SOCK_SEQPACKET)套接字上使用sendto(),则参数dest_addr 和addrlen 将被忽略(如果不使用EISCONN,则可能会返回错误NULL 和 0)
6.我可以在 TCP 连接 recvfrom 的客户端套接字上使用最后 2 个参数为 NULL 吗?
是的。 recv 可以在 TCP 套接字上调用,recv 是根据 recvfrom 定义的,最后两个参数是 NULL。
根据我的 (GNU/Linux) 系统上的man 2 recv:
recv(sockfd, buf, len, flags); 等价于recvfrom(sockfd, buf, len, flags, NULL, NULL);