我面临一个奇怪的问题,也许这很简单,但我缺乏太多的插座知识也无济于事。
我已经创建了一个套接字程序,它在一个单独的程序中运行时非常有效,即在main中作为独立的exe分别运行。正如您在代码中看到的那样,在此单独程序中运行时返回的套接字fd始终为3。
当我复制相同的代码并将其集成到另一个已经打开了fd的服务器程序时,无论如何,select总是返回0。在这种情况下用我的程序创建的fd总是6。
请参阅下面的我的计划。这段代码没有问题,只是当它在另一台服务器中运行时,select总是返回0。
如果程序中已存在一个新的UDP套接字fd,是否可以创建它。 当我的socket fd与程序中已经打开的不同时,为什么会发生这种情况。
为什么会发生这种情况,任何人都可以指导我做什么或任何指针都会有所帮助。
#define MY_TIMEOUT_S 5
int mySock;
if ((mySock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Cannot create UDP socket");
return -1;
}
struct sockaddr_in myAddr;
myAddr.sin_family = AF_INET;
myAddr.sin_port = 0;
myAddr.sin_addr.s_addr = INADDR_ANY;
memset(&(myAddr.sin_zero), '\0', 8);
if (bind(mySock, (struct sockaddr*)&myAddr,
sizeof(struct sockaddr)) == -1) {
perror("Cannot bind UDP socket to desired port");
close(mySock);
return -1;
}
// here send to remote target host on udp socket and port
char buf[MAX_UDP_PACKET_SIZE];
struct sockaddr_in theirAddr;
int addrLen = sizeof(struct sockaddr);
fd_set readSet, curReadSet;
FD_ZERO(&readSet);
FD_SET(mySock, &readSet);
int maxFD = mySock;
while (true) {
struct timeval timeOutTV = {MY_TIMEOUT_S, 0};
memcpy(&curReadSet, &readSet, sizeof(fd_set));
int selectRet = select(maxFD+1, &curReadSet, NULL, NULL, &timeOutTV);
cout<<"select value =" <<selectRet<<endl;
if (selectRet == -1) {
if (errno == EINTR) {
continue; // Interrupted by signal, retry
}
close(mySock);
return -1;
} else if (selectRet == 0) {
close(mySock);
return -1;
}
if (FD_ISSET(mySock, &curReadSet)) {
int numBytes = recvfrom(mySock, buf, MAX_UDP_PACKET_SIZE, 0,
(struct sockaddr*)&theirAddr, (socklen_t*)&addrLen);
if (numBytes == -1) {
close(mySock);
}
}
}
从lsof输出中添加一些细节
1)这是我必须发送数据的目标 sudo lsof -a -p 16061
目标16061 root 3r FIFO 0,8 0t0 153467管道
目标16061 root 4u IPv4 153470 0t0 UDP *:3290
目标16061根5u袜子0,6 0t0 153471无法识别协议
目标16061 root 6u IPv4 153472 0t0 TCP *:3290(LISTEN)
目标16061 root 7u raw 0t0 153473 00000000:0001-> 00000000:0000 st = 07
2)这是我在上面的一段代码,当在一个单独的exe中运行时,只有这是在main中运行的代码 因为FD = 3工作正常
sudo lsof -a -p 16112
myProg 16112 root 0u CHR 136,4 0t0 7 / dev / pts / 4
myProg 16112 root 1u CHR 136,4 0t0 7 / dev / pts / 4
myProg 16112 root 2u CHR 136,4 0t0 7 / dev / pts / 4
myProg 16112 root 3u IPv4 153564 0t0 UDP *:60503
3)这是我整合上面相同代码的网络服务器,它独立工作,但现在不是
这是我运行的网络服务器的输出
webServ 18431 root 3u unix 0xc09f9b00 0t0 157975 socket
webServ 18431 root 4u IPv4 157976 0t0 UDP *:8080
webServ 18431 root 5u IPv4 157977 0t0 TCP *:8080(LISTEN)
现在我发送请求并在服务器端执行我的新集成代码并且我放置了一个无限循环并且没有关闭套接字只是为了显示lsof输出
4)整合后的输出
webServ 18449 root 3u unix 0xc09f9b00 0t0 157975 socket
webServ 18449 root 4u IPv4 157976 0t0 UDP *:8080
webServ 18449 root 5u IPv4 157977 0t0 TCP *:8080(LISTEN)
webServ 18449 root 6u IPv4 158389 0t0 UDP *:48057
唯一的区别是当集成到服务器时,套接字FD是不同的,这是唯一的区别。
希望这有助于回答我的问题。
我不确定为什么会这样。请帮忙
答案 0 :(得分:0)
select
maxFd + 1
可能有帮助吗?
编辑:我再次查看了您的代码(尽管您现在可能已经解决了这个问题)。我有三个建议。
首先,当您bind
套接字时,myAddr.sin_port
为0
。因此选择了一个短暂的端口号。此myProg和webServ程序之间的端口号不同:
myProg 16112 root 3u IPv4 153564 0t0 UDP *:60503
webServ 18449 root 6u IPv4 158389 0t0 UDP *:48057
所以我很困惑你使用什么端口号将UDP发送到myProg。
其次,select
的超时为5秒,然后关闭套接字并离开。你怎么知道在打开端口后5秒内你会收到一个数据包?为了确保这一点,发送程序将需要(例如)每4秒或更短时间不断尝试发送一个数据包,这似乎不合理。
第三,这可能是一个小问题,但可能是你的问题,在:
if (numBytes == -1) {
close(mySock);
}
你省略了你在别处使用的return -1;
,所以如果recvfrom
返回错误,例如EINTR,你将陷入无限循环。此外,在这里和其他地方调用perror
会很不错。
最后,评论:
// here send to remote target host on udp socket and port
不正确,您正在接收。
答案 1 :(得分:0)
制作:
int maxFD = mySock + 1;
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
nfds 是三个集合中任意一个的编号最高的文件描述符,加1 。