Problems receiving data through a TCP client socket

I am trying to make a TCP Client program in C, where the client will start, connect to the server. Then he will send a little information, and then just listen to what he receives and will respond accordingly.

The part I'm having problems with is continuous listening. That's what i

... while (1) { numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0); buf[numbytes] = '\0'; printf("Received: %s\n", buf); // more code to react goes here } ... 

After connecting to the server, after sending two lines of data, the server should get a good bit of information, but when I run it, it prints:

Received:

And then she continues to sit there until I make him close.

** EDIT ** when I do what Jonathan told me, I get the following:

Count: -1, Error: 111, Received:

So that means his mistake, but what can I do about it?

+3
source share
4 answers

Print the number of bytes received - it will probably be zero, but confirm this.

It would be nice to verify that you are not receiving an error message - and therefore overflow your buffer.

[Note: from here on, Pax's work - thanks , and I converted it to the Community Wiki, so I don't get rep rep undeservedly.]

The following code will do this. Try and report the results, please.

 while (1) { numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0); buf[numbytes] = '\0'; printf("Count: %d, Error: %d, Received: %s\n", numbytes, errno, buf); // more code to react goes here } 

After editing the question:

Error number 111 ECONNREFUSED is not an ordinary error code for recv (), but is more suitable for calling an open type (open (), connect (), etc.).

In any case, ECONNREFUSED is a problem on the server, not the client - the server deliberately refused to accept your incoming connection, so you will need to examine this end of the link.

To verify this, change your code so that it connects to www.microsoft.com on port 80 and then sends a couple lines of any old garbage. You must return an error from your web server by specifying an invalid HTTP request. This will not be a problem for your client.

This is what I will return when I telnet www.microsoft.com 80 and type hello and then ENTER twice:

 HTTP/1.1 400 Bad Request Content-Type: text/html; charset=us-ascii Server: Microsoft-HTTPAPI/2.0 Date: Thu, 27 Nov 2008 01:45:09 GMT Connection: close Content-Length: 326 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd"> <HTML><HEAD><TITLE>Bad Request</TITLE> <META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD> <BODY><h2>Bad Request - Invalid Verb</h2> <hr><p>HTTP Error 400. The request verb is invalid.</p> </BODY></HTML> 

You should see something like this.

+4
source

I highly recommend the Beej Guide to Network Programming .

In this section , in particular, there is code for the client that does exactly what you ask.

+2
source

EDIT: The answer below was based on a misunderstanding of the question - the OP code is actually trying to recv () on the socket, which it opens () ed on the remote server. Material below left for posterity.


Please show more of your code.

A few observations:

  • is the listen()ing socket?
  • You have an accept()ed incoming connection
  • It's a little unusual to use recv() on a TCP socket. Use read() instead.
  • use strerror() to convert the 111 error code to a local error string - each UNIX O / S can have its own mapping from numbers to Exxx error codes, so we cannot say what the error is on your system.

The normal code loop (for a single-threaded application without forking) looks like this:

 s = socket(); err = listen(s, n); // n = backlog number while (1) { int fd = accept(s, &addr, sizeof(addr)); while (1) { int numrecv = read(fd, ...); // break if eof } close(fd); } close(s); 
0
source

What about an infinite loop? Why not use select () so that you only call recv () when there is actual data to read?

In a previous life, I wrote network code for MUD, and I can still write a polling cycle in my head. The loop in ROM 2.3 went something like this (from memory, so forgive me if the macro options are in the wrong order):

 #define MAX_CONNECTIONS 256 int main(int argc, char *argv[]) { int i = 0; int running = 1; int connections[MAX_CONNECTIONS]; while( running ) { fd_set in_fd, out_fd, exc_fd; FD_ZERO(in_fd); FD_ZERO(out_fd); FD_ZERO(exc_fd); for( i = 0; i < MAX_CONNECTIONS; i++ ) { if( connections[i] > 0 ) { FD_SET(&in_fd, connections[i]); FD_SET(&out_fd, connections[i]); FD_SET(&exc_fd, connections[i]); } } select(&in_fd, &out_fd, &exc_fd, NULL); // this will block until there an I/O to handle. for( i = 0; i < MAX_CONNECTIONS; i++ ) { if( FD_ISSET(&exc_fd, connections[i]) ) { /* error occurred on this connection; clean up and set connection[i] to 0 */ } else { if( FD_ISSET(&in_fd, connections[i]) ) { /* handle input */ } if( FD_ISSET(&out_fd, connections[i]) ) { /* handle output */ } } } } } 
0
source

All Articles