user1816546
user1816546

Reputation: 313

Client connects to server randomly

I am trying to write a simple client/server program where the server first connects to the client, and sends the client a message. The client then echoes back the message to the server in uppercase.

The thing is, the connection is random; sometimes the client connects and sometimes it doesn't.

EDIT: when it doesn't connect, I get an "Address already in use" error. Is there some way to free the address on the server side?

SERVER.C

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>

int main(){
  int welcomeSocket, newSocket, portNum, clientLen, nBytes;
  char buffer[1024];
  struct sockaddr_in serverAddr;
  struct sockaddr_storage serverStorage;
  socklen_t addr_size;
  int counter = 0;

  welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);

  portNum = 7891;

  serverAddr.sin_family = AF_INET;
  serverAddr.sin_port = htons(portNum);
  serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);  

  bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));

  /*---- Listen on the socket, with 5 max connection requests queued ----*/
  if(listen(welcomeSocket,5)==0)
    printf("Listening\n");
  else
    printf("Error\n");

  /*---- Accept call creates a new socket for the incoming connection ----*/
  addr_size = sizeof serverStorage;
  while(1){
      newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
/*    counter ++ ;*/
/*    printf("client connected: %d\n",counter);*/
      /*fork a child process to handle the new connection*/
      if(!fork()){
          /*---- Send message to the socket of the incoming connection ----*/
          strcpy(buffer,"Hello World\n");
          send(newSocket,buffer,13,0);
          recv(newSocket,buffer,13,0);

          /*---- Print the received message ----*/
          printf("Data received: %s",buffer);
          close(newSocket);
          exit(0);
      }
      /*if parent, close the socket and go back to listening new requests*/
      else{
          close(newSocket);
      }       
  }

  return 0;
}

CLIENT.C

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <ctype.h>

int main(){
  int clientSocket, portNum, nBytes;
  char buffer[1024];
  struct sockaddr_in serverAddr;
  socklen_t addr_size;

  clientSocket = socket(PF_INET, SOCK_STREAM, 0);

  portNum = 7891;

  serverAddr.sin_family = AF_INET;
  serverAddr.sin_port = htons(portNum);
  serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
  memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);  

  /*---- Connect the socket to the server using the address struct ----*/
  addr_size = sizeof serverAddr;
  connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);

  /*---- Read the message from the server into the buffer ----*/
  nBytes = recv(clientSocket, buffer, 1024, 0);

  /*---- Print the received message ----*/
  printf("Data received: %s",buffer);   

  for (int i=0;i<nBytes-1;i++){
     buffer[i] = toupper(buffer[i]);
  }

  send(clientSocket,buffer,nBytes,0);


  return 0;
}

Upvotes: 0

Views: 153

Answers (1)

dbush
dbush

Reputation: 224917

The "address already in use" error occurrs on a call to bind when a socket is already bound to that port. In the case of a listening TCP socket, that can happen when the program is restarted due to old connected sockets not being completely closed yet.

When binding a listening socket, you should set the SO_REUSEADDR socket option. This will allow you to bind a TCP listening socket in these situations.

int option = 1;
if (setsockopt(welcomeSocket, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) == -1) {
    perror("setsockopt for SO_REUSEADDR failed");
    exit(1);
}

This function should be called after socket but before bind.

Upvotes: 2

Related Questions