2

I have the following code:

  bytes_read = read(0, buffer_stdin, 65535);
  printf("bytes read from stdin: %d\n", bytes_read);
  bytes_written = write(sock, buffer_stdin, bytes_read);
  printf("bytes written to socket: %d\n", bytes_written); 

sock is the socket descriptor. In the code I have connected the socket to a server and the connection returned (0), indicating the connection was successful.

Now in the code above I type something into stdin, let's say "hello" and the number of bytes read would be 6 (because of null termination after letter 'o'). The program executes the first print statement.

But for some reason the program doesn't execute the second print statement. It just exits.

When I commented out line 3 where I write to the socket, the 2nd print statement executes.

My question is, why is the program exiting early without my instruction to do so?

Here is the preliminary code:

int main(int argc, char *argv[]) {
  if (argc != 3) {
    printf("Invalid arguments\n");
    exit(1);
  }

  char *serverIP = argv[1]; /*Server hostname*/
  char *portNumber = argv[2]; /*Port Number*/
  void *numericAddress;
  char buffer_stdin[65535];
  char buffer_stdout[65535];
  int bytes_read = 0;
  int bytes_written = 0;

  /*getting integral number of string representation of port number*/
  in_port_t servPort = atoi(argv[2]);

  /*------------------get binary number of hostname-----------------*/
  struct addrinfo addrCriteria;
  memset(&addrCriteria, 0, sizeof(addrCriteria));
  addrCriteria.ai_family = AF_INET;
  addrCriteria.ai_socktype = SOCK_STREAM;
  addrCriteria.ai_protocol = IPPROTO_TCP;

  struct addrinfo *addrList;

  int rtnVal = getaddrinfo(serverIP, portNumber, &addrCriteria, &addrList);
  if (rtnVal != 0) {
    printf("getaddrinfo() failed\n");
    exit(1);
  }
  if (rtnVal == 0) {
    printf("getaddrinfo() successful\n");
  }

  numericAddress = &((struct sockaddr_in *) (addrList->ai_addr))->sin_addr;
  ((struct sockaddr_in *)(addrList->ai_addr))->sin_port = htons(servPort);
  /*----------------------------------------------------------------*/

  /*Creating socket*/
  int sock = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
  if (sock < 0) {
    printf("error creating socket\n");
    exit(1);
  }

  /*Establish connection to the echo server*/
  int r = connect(sock, (struct sockaddr *) addrList, sizeof(addrList));
  if (r < 0) {
    printf("Connection failed\n");
    exit(1);
  }
  if (r == 0) {
    printf("connection succesful\n");
  }
umdcoder
  • 137
  • 1
  • 2
  • 15
  • What is the server doing after you connect to it? – jxh Sep 11 '14 at 21:57
  • 1
    The number of bytes read would be 6 because of the "\n", not because of the null termination (which isn't read). – Xaqq Sep 11 '14 at 22:01
  • 1
    Please show the remainder of your code where you create your socket and connect to the remote. There problem appears to be outside the code your provided. – David C. Rankin Sep 11 '14 at 22:01
  • @Xaqq oh ya my bad I forgot. that applies to things like strings – umdcoder Sep 11 '14 at 22:03
  • @jxh the server is just waiting for a connection from the client (me). This is supposed to be an echo server. I send something to the server, like "hello", and the server should send that message back to me. – umdcoder Sep 11 '14 at 22:04
  • Dollars to bitcoins that your server has closed the connection before you sent any data, so please validate your assumptions. – jxh Sep 11 '14 at 22:08
  • @jxh, what I am saying is that this code is supposed to be a client trying to connect to the server which sends back whatever it received – umdcoder Sep 11 '14 at 22:10
  • I thought I was clear. Make sure the server is not closing the connection before your client is sending. – jxh Sep 11 '14 at 22:12
  • Or perhaps the server didn't do everything it needs to, please show us the code where the server listens and accepts the connection – John Hascall Sep 11 '14 at 22:13
  • A sudden program-exit during a call to write() sounds suspiciously like a SIGPIPE signal is being raised due to a write on a remotely-closed socket. I suggest disabling the SIGPIPE signal as described here: http://stackoverflow.com/questions/108183/how-to-prevent-sigpipes-or-handle-them-properly – Jeremy Friesner Sep 11 '14 at 22:15
  • @JeremyFriesner: That is the suspicion, but disabling SIGPIPE addresses the symptom, not the root cause. – jxh Sep 11 '14 at 22:16
  • We don't have access to the code that is used to write the server. We have been given a file called exe that is essentially the server. We were told to type in "chmod a+x exe" and then "./exe " in our linux command line to set up the server. – umdcoder Sep 11 '14 at 22:19
  • Then once we do that, we type in something like: echo "echo test" | ./ – umdcoder Sep 11 '14 at 22:21
  • What port are you choosing? – jxh Sep 11 '14 at 22:22
  • That is a well-known port (and privileged). Choose something else. At least 4 digits. – jxh Sep 11 '14 at 22:30
  • Calling read() inputs only the characters from std in. I.E. there is NO terminating null char. The code has to insert the trailing null char, by using the value returned from read() as an offset into the buffer. Actually it would be better to clear the buffer to null first, before the read. Is your buffer actually 65535 bytes long? a better third parm to read() would be (sizeof buffer_stdin -1) – user3629249 Sep 12 '14 at 06:33
  • The first printf() will be trying to print trash after the first 6 characters. That is why the program crashed. – user3629249 Sep 12 '14 at 06:35

1 Answers1

3

SIGPIPE

The problem seems to be that the server closed the connection before your client had a chance to send data. Writing to a closed socket could result in a kind of error that is expressed as raising the SIGPIPE signal, unless that signal has been ignored. If the signal delivery of SIGPIPE has been suppressed (by setting its disposition to SIG_IGN), writing to a closed socket will cause an error result with errno set to EPIPE.

Since your program does not ignore SIGPIPE or otherwise hand it, the default handler is used, which would likely cause the program to terminate. This explains your immediate problem.

Privileged port 80

You indicated in comments that you used port 80 for your "echo server". Unless you are running the program as root, 80 is within the privileged port range, so your program would not be able to listen on that port. In addition, port 80 is the well known port for the HTTP service. So, even if you started the "echo server" with root privileges, it would still likely fail because some other server (the web server) would already be listening on that port.

Assuming you directed your client at the web server, it is unknown what actually happened when your client attempted communication. For example, the web server may have delivered a RST packet as soon as the client connected. The connection completed successfully, but writing would fail.

To get the behavior you expect, you should choose an unprivileged port for your "echo server". Something relatively high and random, so that it will not conflict with other programs, and will not conflict with other users if you are on a shared machine.

jxh
  • 69,070
  • 8
  • 110
  • 193