[英]C socket - not all socket receive in select()
我的多線程項目有一個問題:我創建了一些線程,這些線程必須彼此發送和接收udp消息,因此每個線程都使用select()在多個套接字上偵聽。 問題是:只有最后一個套接字插入fd_set變量中,才能接收消息。 我不知道為什么
這是代碼:
線程的初始部分:
int fdmax;
fd_set read_fd_set, service_fd_set;
/* allocate memory for receive msg */
msg=malloc(sizeof(char)*(SIZEBUF));
FD_ZERO(&read_fd_set);
FD_ZERO(&service_fd_set);
fdmax=0;
if (param->n_port != 0){
for (x=0; x<(param->n_port); x++){
/* take the port from array */
local_port_number = param->l_port_in[x];
/* create socket udp and bind on localhost */
socketfd=create_socket(local_port_number);
/* save socket_fd in my data struct */
param->sock_fd_local[x]=socketfd;
/* add socket in fd_set */
FD_SET(socketfd,&service_fd_set);
if (socketfd > (fdmax-1)){
fdmax=socketfd + 1;
}
線程的第二部分:
for(;;){
read_fd_set=service_fd_set;
ris=select(fdmax,&read_fd_set,NULL,NULL,NULL);
if(ris<0){
if (errno!=EINTR){
printf(_KRED "Error in select: errno different from EINTR \n" _KNRM);
}
}
if (ris>0){
for(p=0; p<fdmax; p++){
if((FD_ISSET(p,&read_fd_set))!=0){
for( x=1; x<=5; x++){
if( p == param->sock_fd_local[x]){
/* setup datagram to receive */
memset(&From, 0, sizeof(From));
Fromlen=sizeof(struct sockaddr_in);
/* RECVFROM */
msglen = recvfrom ( p, msg, (int)SIZEBUF, 0, (struct sockaddr*)&From, &Fromlen);
if (msglen<0){
...
}else{
sprintf((char*)string_remote_ip_address,"%s",inet_ntoa(From.sin_addr));
remote_port_number = ntohs(From.sin_port);
print_msg(...);
}
}
}
}
}
}
}
有人可以幫助我嗎?
整個項目在這里: https : //github.com/bonfi/SpanningTreeUDP
(對不起,我的英語,我是意大利語,該項目用意大利語發表了評論)
我相信至少有一個甚至兩個問題。 第一個是在第二部分的recvfrom函數中,您正在使用socketfd,但未將其設置為要從中接收數據的套接字。 變量socketfd包含您從初始代碼創建的最后一個套接字。 我懷疑這就是為什么您僅從一個線程(它是最后創建的套接字)獲取數據的原因。
我不太了解的另一項是第二部分中帶FD_ISSET的if語句之后的循環。 我不確定為什么要用x循環然后設置p或為什么要進行4次。
我建議第二部分中的代碼應類似於以下以FD_ISSET if語句開頭的代碼。
if((FD_ISSET(p,&read_fd_set))!=0){
socketfd == param->sock_fd_local[p]){
/* setup datagram to receive */
memset(&From, 0, sizeof(From));
Fromlen=sizeof(struct sockaddr_in);
/* RECVFROM */
msglen = recvfrom ( socketfd, msg, (int)SIZEBUF, 0, (struct sockaddr*)&From, &Fromlen);
if (msglen<0){
...
}else{
sprintf((char*)string_remote_ip_address,"%s",inet_ntoa(From.sin_addr));
remote_port_number = ntohs(From.sin_port);
print_msg(...);
}
}
我使用x變量刪除了for循環,並使用p來對結構進行索引,以根據FD_ISSET是否返回true來設置用於接收數據的socketfd。 這樣,您可以根據文件描述符(如果已設置)來設置socketfd變量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.