我正在编写一个简单的TCP服务器和客户端,服务器将消息回送给客户端。但是我遇到了来自客户端的第一个read()/ recv()调用问题。每当客户端连接到服务器时,它都会发送一条欢迎消息,但我无法在客户端显示欢迎消息。我从recv()/ read()返回的是0,表示套接字已关闭或0字节读取。我知道它没有关闭,因为服务器回送消息但有延迟(例如下面的例子)。从客户端写入服务器后,read()/ recv()工作正常。所以我的问题是: 为什么第一个read()/ recv()调用接收返回0?
TLDR;我的客户端不读取()/ recv()从服务器发送的欢迎消息。我做错了什么?
如您所见,套接字未关闭,因此read()/ recv()返回0的唯一原因是因为读取了0个字节。
客户代码:
(SETUP NOT INCLUDED)
printf("Connected. \n");
memset(buffer, 0, 1025);
/********* PROBLEM IS THIS READ()/RECV() **********/
n = recv(sockfd, buffer, strlen(buffer), NULL);
if(n == 0){ //
//error("Error reading\n");
printf("Error reading socket.");
}
printf("Welcome message: \n%s", buffer);
while(1){
printf("\nPlease enter message: \n");
memset(buffer, 0, 256);
fgets(buffer, 255, stdin);
printf("You sent: %s", buffer);
n = write(sockfd, buffer, strlen(buffer));
if(n <= 0)
{
error("Error writing socket. \n");
}
//om bye, break
memset(buffer, 0, 256);
//Läser här endast efter write
n = read(sockfd, buffer, 255);
if(n < 0)
{
error("Error reading from socket. \n");
}
printf("You received: %s", buffer);
}
//end while
close(sockfd);
return 0;
相关服务器代码:
while(TRUE)
{
/* Clear socket set */
FD_ZERO(&readfds);
/* Add master socket to set */
FD_SET(masterSocket, &readfds);
/* For now maxSd is highest */
maxSd = masterSocket;
/* Add child sockets to set, will be 0 first iteration */
for(int i = 0; i < maxClients ; i++)
{
sd = clientSockets[i]; // sd = socket descriptor
/* If valid socket descriptor */
if(sd > 0)
{
FD_SET(sd, &readfds);
}
/* Get highest fd number, needed for the select function (later) */
if(sd > maxSd)
{
maxSd = sd;
}
}//end for-loop
/* Wait for activity on any socket */
activity = select(maxSd +1, &readfds, NULL, NULL, NULL);
if((activity < 0) && (errno != EINTR))
{
printf("****** Error on select. ******\n"); //no need for exit.
}
/* If the bit for the file descriptor fd is set in the
file descriptor set pointed to by fdset */
/* If something happend in the master socket, its a new connection */
if(FD_ISSET(masterSocket, &readfds))
{
//står här och läser
if((newSocket = accept(masterSocket, (struct sockaddr*)&address, (socklen_t*)&addrlen)) < 0)
{
perror("****** Could not accept new socket. ******\n");
exit(EXIT_FAILURE);
}
/* Print info about connector */
printf("New connection, socket fd is %d, ip is: %s, port: %d\n", newSocket, inet_ntoa(address.sin_addr), ntohs(address.sin_port));
/**************** THIS IS THE WRITE THAT DOESN'T GET DISPLAYED ON CLIENT ******************/
if( send(newSocket, message, strlen(message), 0) != strlen(message))
{
perror("****** Could not sent welcome message to new socket. ******\n");
}
puts("Welcome message sen successfully");
/* Add new socket to array of clients */
for(int i = 0; i < maxClients; i++)
{
if(clientSockets[i] == 0)
{
clientSockets[i] = newSocket;
printf("Adding socket to list of client at index %d\n", i);
break;
}
}
}//end masterSocket if
/* Else something happend at client side */
for(int i = 0; i < maxClients; i++)
{
sd = clientSockets[i];
if(FD_ISSET(sd, &readfds))
{
/* Read socket, if it was closing, else read value */
//denna read kan vara fel
if((valread = read( sd, buffer, 1024)) == 0)
{
getpeername( sd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
printf("Host disconnected, ip %s, port %d.\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));
close(sd);
clientSockets[i] = 0;
}
else
{
buffer[valread] = '\0';
send(sd, buffer, strlen(buffer), 0);
}
}
}
我知道这是一个很大的文字墙,但我非常感谢那些花时间解决这个问题的人。
答案 0 :(得分:2)
我不确定这是否是问题的唯一原因,但是......在您的客户代码中......
memset(buffer, 0, 1025);
然后不久......
n = recv(sockfd, buffer, strlen(buffer), NULL);
此时 strlen(buffer)
将返回零,因此对recv
的调用完全按照请求执行 - 它读取零字节。
另请注意,服务器发送的欢迎消息不会以空值终止。因此,您的客户端无法知道欢迎消息何时结束以及后续数据何时开始。
答案 1 :(得分:2)
recv
的第三个arg指定从套接字读取的字节数。现在看看你的代码:
memset(buffer, 0, 1025);
recv(sockfd, buffer, strlen(buffer), NULL);
首先,将整个缓冲区归零,然后在其上调用strlen
。难怪它返回0,因为strlen
计算非零字节。
相反,将缓冲区长度放入变量并在任何地方使用它:
const int bufSize = 1025;
memset(buffer, 0, bufSize);
recv(sockfd, buffer, bufSize, NULL);