[英]socket recv() doesn't receive data
我有一個服務器守護進程監聽 TCP unix 域/本地套接字。 在同一台機器上運行的多個客戶端連接到它。 該守護進程還綁定到 UDP Inte.net 套接字。 每當守護程序從其中一個本地客戶端接收到任何數據時,它都會將相同的數據發送到除發送客戶端之外的所有連接的客戶端。 如果守護進程在 UDP inte.net 套接字上接收到數據,它需要將該數據發送到所有本地連接的客戶端。 當守護程序在本地套接字上接收數據時,數據的發送/接收工作完美。 但是,當服務器向客戶端發送在 UDP inte.net 套接字上接收到的數據時,客戶端不會收到任何數據。 在服務器守護程序退出並關閉連接后,或者在任何客戶端將數據本地發送到服務器時,客戶端會收到該 inte.net 數據。 inte.net 數據與本地數據一起由客戶端接收。 我已使用fcntl()
將本地和 .net sockets 設置為阻止。 這是我擁有的守護程序代碼(我刪除了所有不必要的代碼):
while(1)
{
FD_SET(sockfd, &read_fds);
FD_SET(inet_sock, &read_fds);
for (i = 0; i < nclients; i++)
{
FD_SET(clients[i], &read_fds);
}
select(maxfd + 1, &read_fds, &write_fds, &except_fds, NULL);
/* Check for events on inet sock */
if (FD_ISSET(inet_sock, &read_fds))
{
/* Read from inet sock */
socklen = sizeof(dest_sin);
rval = recvfrom(inet_sock, buf, BUFLEN-1, MSG_DONTWAIT,
(struct sockaddr *) &dest_sin, &socklen);
buf[rval]=0;
fprintf(stderr, "Received: %d (%d) bytes containing %s", rval, strlen(buf), buf);
/* Send the message to every other client */
for(j=0; j < nclients; j++)
{
send(clients[j], buf, strlen(buf), MSG_DONTWAIT);
}
}
/* A read event on the local socket is a new connection */
if (FD_ISSET(sockfd, &read_fds))
{
socklen = sizeof(dest_sun);
/* Accept the new connection */
rval = accept(sockfd, (struct sockaddr *) &dest_sun, &socklen);
/* Add client to list of clients */
clients[nclients++] = rval;
if (rval > maxfd) maxfd = rval;
snprintf(s, BUFLEN, "You are client %d [%d]. You are now connected.\n\0",
nclients, rval);
send(rval, s, strnlen(s, BUFLEN), MSG_DONTWAIT);
}
/* Check for events from each client */
for (i = 0; i < nclients; i++)
{
fprintf(stderr,"Checking client %d [%d] for read indicator.\n",i, clients[i]);
/* Client read events */
if (FD_ISSET(clients[i], &read_fds))
{
fprintf(stderr, "Client %d [%d] marked for read.\n", i, clients[i]);
/* Read from client */
rval=recv(clients[i], buf, BUFLEN-1, MSG_DONTWAIT);
buf[rval]=0;
fprintf(stderr, "Received: %d (%d) bytes containing %s", rval, strlen(buf), buf);
/* Send the message to every other client */
for(j=0; j < nclients; j++)
{
/* Skip the sender */
if (j == i) continue;
/* Send the message */
send(clients[j], s, strlen(s, BUFLEN), MSG_DONTWAIT);
}
}
}
}
這是我的客戶端代碼:
while(1)
{
FD_SET(fileno(stdin), &read_fds);
FD_SET(sockfd, &read_fds);
select(fileno(stdin) > sockfd ? fileno(stdin)+1 : sockfd+1,
&read_fds, &write_fds, &except_fds, NULL);
if (FD_ISSET(sockfd, &read_fds))
{
/* Read from socket and display to user */
mlen = recv(sockfd, (void *)buf, BUFLEN-1, MSG_DONTWAIT);
buf[mlen]=0;
printf("Received %d bytes: %s", mlen, buf);
}
if (FD_ISSET(fileno(stdin), &read_fds))
{
fgets(buf, BUFLEN, stdin);
fprintf(stderr, "Sent %d octets to server.",
send(sockfd, (void *)buf, (size_t) strnlen(buf, BUFLEN), 0));
}
}
目標是讓客戶端立即接收守護程序發送給它們的數據(守護程序在其 .net 套接字上接收的數據)。
編輯:我發現當守護進程發送數據時,客戶端的 select() 返回套接字可讀,但 recv() 正在阻塞,這就是我沒有在客戶端獲取數據的原因。 對於如何解決這個問題,有任何的建議嗎?
這是從您的代碼中提取和對齊的send()
調用:
send(clients[j], buf, strlen(buf), MSG_DONTWAIT);
send(rval, s, strnlen(s, BUFLEN), MSG_DONTWAIT);
send(clients[j], s, strlen(s, BUFLEN), MSG_DONTWAIT);
我在這里看到了一些不一致之處。 有時你調用strlen()
,有時調用strnlen()
,有時調用 strlen( strlen()
兩個 arguments (我什至不知道那會做什么)。
您看到的問題可能與您沒有在顯示消息之間邊界的套接字上發送任何信息這一事實有關。 在 stream 套接字上,不會保留消息邊界,您應該注意在協議中包含適當的幀信息,以便接收方可以提取各個消息。 您不能依賴於通過recv()
調用的字節數與send()
調用中的字節數完全相同。 您將以相同的順序獲得相同的字節總數(這是 stream 套接字的重點),但消息可能會合並或拆分,您無法控制。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.