0

I set up a simple client and server program using TCP socket to communicate. The server waits for the client to connect and reply whether it receives the message from the client. Below is how the code is implemented in the server and the client:

Code on the server-side:

 listen(sockfd,5);

 clilen = sizeof(cli_addr);
 newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

 if (newsockfd < 0)
      error("ERROR on accept");
 bzero(buffer,256);

 n = read(newsockfd,buffer,255);

 if (n < 0)
     error("ERROR reading from socket");

 printf("Here is the message: %s\n",buffer);

 n = write(newsockfd,"I got your message",18);

 if (n < 0)
     error("ERROR writing to socket");

Code on the client-side:

if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
    error("ERROR connecting");
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
     error("ERROR writing to socket");
else
    printf("sucess. n = %d", n);

bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
     error("ERROR reading from socket");

Now, assume that I starts the server and then starts the client, the client successfully connects to the server. Then I shuts down the server and tries to send a message from the client, the write() operation returns no error. What I expect here is an error because the server actually does not receive any packets (it is shut down).

So my question is: is there any way to know whether the write() (or send(), sendto() or sendmsg()) successfully delivers the message to the server?

Hieu Nguyen
  • 382
  • 2
  • 15
  • Many people ask, "if the TCP stack knows that that packet has been acknowledged (ACK'd) by the remote host, why can't my application code ascertain this?" The reason being is that the TCP only knows if the packet was ACK'd by the TCP layer of the remote host. It has no knowledge if the data being acknowledged was actually consumed by the application hosting the socket on the remote side. Hence, the higher level prototols above TCP (i.e. your code and protocol) need to provide this signaling. – selbie Feb 03 '14 at 07:33

2 Answers2

4

No. Write or send just do the talking, they don't wait for feedback (e.g. ACK in case of TCP). But you can only be sure that the message was delivered successfully, if you got some kind of feedback. It does not even help to try another send because it might be executed while the previous message is not yet at the client. It also does not help to recv and hope for error, because the data you receive might hace been sent by the peer before you even sent your message. The only way to be really sure is to put some kind of explicit handshake in your application protocol and wait for the matching response to your message.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • I searched for this issue and it seems that when the server stopped, a SIGPIPE signal is sent to the client, but I still dont know how the client catches and handles this signal. – Hieu Nguyen Feb 03 '14 at 04:19
  • 2
    Kind of: if the TCP connection is closed and you try to send() or write() again you get a SIGIPE or if you ignore the signal the system call returns EPIPE. But it is not, that the server sends the the signal to the client, it just closes the connection. – Steffen Ullrich Feb 03 '14 at 05:11
1

It does not work that way. write() returns success as soon as message fits in the send buffer. The only way to know that message was received and processed by the server is receiving e parsing the "I got your message".

write() returns -1 then the connection is already known to be closed or invalid, but don't count on that to detect all possible errors.

epx
  • 1,066
  • 9
  • 17
  • First paragraph is correct but there's too much misinformation in the second paragraph. write() only returns zero if you pass a zero length. If you call it on a closed socket, it returns -1 with errno set to EBADF. If you call it on a connection that has been closed by the peer, it returns -1 with errno set to ECONNRESET. -1 by itself doesn't indicate 'invalid connection'. – user207421 Feb 03 '14 at 02:24
  • Well the idea is to fix the answer actually. – user207421 Feb 03 '14 at 06:33