>但是在这种情况下我的绑定调用不应该失败吗,
如果套接字没有设置 SO_REUSEADDR 选项,则是。
> 如果是这样,我该如何设置套接字以使用已被另一个应用程序使用的本地端口?
您的应用程序和另一个应用程序都必须在要绑定到本地端口的套接字上设置 SO_REUSEADDR 选项。
以下代码从端口 1111 以命令行参数的形式连接到 HTTP 服务器:
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <netdb.h>
#define CLIENT_PORT 1111
#define SERVER_PORT 80
int main(int argc, char *argv[]) {
struct sockaddr_in client_name, server_name;
struct hostent *server_info;
if (argc != 2)
return printf("Exactly one argument is required: host to connect\n"), 1;
int sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0)
return perror("socket"), 1;
/* Without the next 4 lines, bind refuses to use the same port */
int reuseaddr = 1;
if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
sizeof(reuseaddr)) < 0)
return perror("setsockopt"), 1;
client_name.sin_family = AF_INET;
client_name.sin_port = htons(CLIENT_PORT);
client_name.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock_fd, (struct sockaddr *) &client_name,
sizeof(struct sockaddr_in)) < 0)
return perror("bind"), 1;
server_name.sin_family = AF_INET;
server_name.sin_port = htons(SERVER_PORT);
if ((server_info = gethostbyname(argv[1])) == NULL)
return printf("Unknown host: %s\n", argv[1]), 1;
server_name.sin_addr = *(struct in_addr *) server_info->h_addr;
if (connect(sock_fd, (struct sockaddr *) &server_name,
sizeof(server_name)) < 0)
return perror("connect"), 1;
return 0;
}
>如果我要使用的本地端口已被另一个应用程序使用会怎样?
如果没有 SO_REUSEADDR(尝试注释掉 setsockopt 周围的 4 行),bind 会失败:
$ ./client google.com
$ ./client stackoverflow.com
bind: Address already in use
使用 SO_REUSEADDR,您可以连接到不同的远程服务器:
$ ./client google.com
$ ./client stackoverflow.com
但是 connect 将不允许您打开两个具有相同源 和目标的套接字:
$ ./client google.com
$ ./client google.com
connect: Cannot assign requested address