我想问一下getpeername()函数,因为它返回数据作为标题状态。我试图直接从accept()函数获取值,结果也是一样的。即使地址的值是正确的,端口的值似乎也是随机出现的(地址是127.0.0.1,因为我在一台机器上运行多进程)。 getpeername()的返回码为0(status = 0)。我正在使用gcc版本4.8.1。我写了一个没有服务器的对等2对等聊天应用程序以下是我的代码:
struct sockaddr_in addr;
socklen_t addr_len;
int tempPort, serverSockfd;
char test[100];
// Get serverSockfd successfully....
serverSockFd = initializeSock(PORT) // In this function I initialize socket(), bind() and listen(), serverSockFd is returned by the value of socket()
addr_len = sizeof addr;
newSock = accept(serverSockfd, (struct sockaddr *)&addr, &addr_len);
tempPort = ntohs(addr.sin_port);
inet_ntop(AF_INET, &(addr.sin_addr), test, sizeof test);
printf("tempPort\t%d\n", tempPort);
printf("test\t%s\n", test);
addr_len = sizeof addr;
if ((status = getpeername(newSock, (struct sockaddr *) &addr, &addr_len)) != 0){
printf("getpeername() error!\n");
}
tempPort = ntohs(addr.sin_port);
inet_ntop(AF_INET, &(addr.sin_addr), test, sizeof test);
printf("tempPort\t%d\n", tempPort);
printf("test\t%s\n", test);
非常感谢您的评论。这是initializeSock()中的部分代码:
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd < 0)
{
perror("SocketInit(): socket() error!\n");
exit(1);
}
ret_val = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char*) &flag, sizeof(flag));
if(ret_val == -1)
{
perror("SocketInit(): setsockopt(SO_REUSEADDR) error!\n");
exit(1);
}
gethostname(hostname,100);
host_entry = gethostbyname(hostname);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list));
ret_val = bind(sd, (struct sockaddr*) &addr, sizeof(addr));
if(ret_val == -1)
{
perror("SocketInit(): bind() error!\n");
printf("For port:%d\n",port);
exit(1);
}
....
return sd;
这是连接到对等方的服务器部分的代码。 ConnectSock(portOfPeerA):
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd < 0)
{
perror("ConnectToServer(): socket() error!\n");
exit(1);
}
if (port != 0) {
addr.sin_family = AF_INET;
addr.sin_port = htons(portOfPeerA);
addr.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list));
// Do I need to bind() the port of peer B when it would like to connect to peer A?
ret_val = connect(sd, (struct sockaddr*)&addr, sizeof(addr));
if(ret_val == -1)
{
printf("Error connect());
exit(1);
}
...
答案 0 :(得分:1)
我不知道你从对等端接受哪个端口,但如果对等端连接到你的服务器(例如一个呼叫接受),它将从(或多或少)随机端口连接,这就是TCP的工作方式。只有在连接之前对等体明确绑定到该端口时,它才从固定端口连接。
这意味着,对等体发起端口没有在服务器端(代码片段所在的位置)定义,而是在客户端(调用connect的一侧以及只进行连接但没有绑定的位置)。
但是,请注意,如果客户端和服务器都使用固定的IP和端口,它可能会给重复连接带来问题,因为这样你就可以在TCP中获得相同的4-tupel,它定义了重复连接的连接,从而进入各种TIME_WAIT状态的所有麻烦。因此,最好让客户端选择一个可用的端口,而不是强迫它使用特定的端口。
答案 1 :(得分:1)
getpeername()
(和accept()
)报告远程方本地绑定到的IP和端口。如果远程方是在调用bind()
之前未调用connect()
的客户端,则connect()
执行对随机可用端口的隐式绑定。这就是你所看到的,它是典型的用法。 大多数客户端不需要在bind()
之前调用connect()
,但有些情况需要这样做,所以不要排除它。