I'm writing a simple TCP server and client where the server echoes back the message to the client. But I have a problem with the first read()/recv() call from the client side. Whenever a client connects to the server, it sends a welcome message, but I cannot display the welcome message on the client side. What i get in return from recv()/read() is 0, which indicates that the socket is closed or 0 bytes read. I know it isn't closed since the server echoes back messages but with a delay(example bellow). The read()/recv() works fine after I've written to the server from the client side. So my question is: Why does the first read()/recv() call receive return a 0?
TLDR; My client does not read()/recv() the welcome message sent from server. What am I doing wrong?
Server and client interaction(Notice empty 'Welcome message'):
As you can see, the socket isn't closed so the only reason read()/recv() returns 0 is because 0 bytes read.
Client code:
(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;
Relevant Server code:
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);
}
}
}
I know this is a big wall of text but i am very thankful for anyone who takes their time with this problem.
The third arg to recv
specifies a number bytes to read from the socket. And now look at your code:
memset(buffer, 0, 1025);
recv(sockfd, buffer, strlen(buffer), NULL);
First, you zero out whole buffer and then call strlen
on it. No wonder it returns 0, as strlen
counts non-zero bytes.
Instead, put the buffer length into a variable and use it everywhere:
const int bufSize = 1025;
memset(buffer, 0, bufSize);
recv(sockfd, buffer, bufSize, NULL);