• C

server socket able to accept multiple client connections

I need to make my server socket be able to handle more than one client connection and respond to the client. Basically, the client sends a string then the server repsonds by sending the same string back but in uppercase. I have socket.c which holds all the socket related functions (socket(), recv(), etc) and 2 drivers, testServer.c and testClient.c. There's also a SocketStruch.h which holds the socket fd and the struct sockaddr_in.

I have a function that converts a string to uppercase in socket.c.

SocketStruch.h:
#include <sys/socket.h>

typedef enum { ACTIVE_SOCKET = 234,
               LISTENING_SOCKET,
               BROKEN_SOCKET
} socketType;


struct Socket {
  int sockFD;        // The file descriptor associated with this socket
  socketType sType;  // The type of this socket, it must assigned a value
                     //  from the enumerated type, socketType.
  struct sockaddr_in remoteSockAddr; // This is a convenience field that
                                     // can be used to store addresses
                                     // for setting up a connection or
                                     // for storing the address of a
                                     // received connection.
};

-----------------------------------------------------------------------------------------------
socket.c:

#include "Socket.h"
#include "SocketStruct.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>

/* converts string to uppercase */
void upper(char *str) {
      while (*str) {
            *str = toupper(*str); //convert char to uppercase
            str++;
      }
      
      printf("toupper: %s\n",str);
      
      return str;
}

void *createServerSocket(const int port)
{
  struct Socket *new_socket;
      
      /* allocate memory for struct */
      new_socket = (struct Socket *)malloc(sizeof(struct Socket));
      
      /* create new socket */
      new_socket->sockFD = socket(PF_INET,SOCK_STREAM,0);
      
      /* error checking */
      if (new_socket->sockFD < 0) {
            printf("error, socket creation\n");
            return NULL;
      }
      
      /* setting up server */
      new_socket->remoteSockAddr.sin_family = PF_INET; /* use tcp/ip */
      new_socket->remoteSockAddr.sin_port = port;
      new_socket->remoteSockAddr.sin_addr.s_addr = INADDR_ANY; /* use machine's ip */      
      new_socket->sType = LISTENING_SOCKET;
      
      /* bind server with socket*/
      if (bind(new_socket->sockFD,(struct sockaddr *)&new_socket->remoteSockAddr,
      sizeof(new_socket->remoteSockAddr))<0) {
            perror("error, socket not bound\n");
            return NULL;
      }
      
      /* listen for connection */
      if(listen(new_socket->sockFD,10) < 0) {
            perror("error, listen\n");
            return NULL;
      }
      
  return new_socket;
}

void *createClientSocket(const char *hostname, const int port)
{
  struct Socket *new_socket;
      
      /* allocate memory for struct */
      new_socket = (struct Socket *)malloc(sizeof(struct Socket));
      
      /* creating client socket */
      new_socket->sockFD = socket(PF_INET,SOCK_STREAM,0);
      
      /* error checking */
      if (new_socket->sockFD < 0) {
            perror("error, socket creation\n");
            return NULL;
      }
 
      /* setting up server */
      new_socket->remoteSockAddr.sin_family = PF_INET;
      new_socket->remoteSockAddr.sin_port = htons(port);
      new_socket->remoteSockAddr.sin_addr.s_addr = inet_addr(hostname);
      new_socket->sType = ACTIVE_SOCKET;
      
      /* connect to server */
      if ((connect(new_socket->sockFD,(struct sockaddr *)&new_socket->remoteSockAddr,
                  sizeof(struct sockaddr))) < 0) {
            perror("error, connect");
            return NULL;
      }
 
  return new_socket;
}


void *socketAccept(void *listen_socket)
{
  struct Socket *new_socket;
  new_socket = (struct Socket *)malloc(sizeof(struct Socket));
      
      /* setting up socket */
      new_socket->sType = ACTIVE_SOCKET;
      
      /* cast lsocket to struct Socket */
      struct Socket *lsocket = (struct Socket *)listen_socket;
      
      /* determine size of sockaddr_in */
      int sin_size;
      sin_size = sizeof(struct sockaddr_in);
      
      /* accept connection */
      //while (1) {
      
            //if ((lsocket->sType == LISTENING_SOCKET) || (lsocket->sType == ACTIVE_SOCKET)) {
                  if ((new_socket->sockFD = accept(lsocket->sockFD,
                                          (struct sockaddr *)&lsocket->remoteSockAddr,&sin_size)) < 0) {
                        perror("error, accept");
                        return NULL;
                  }
            
                  if(lsocket->sType == LISTENING_SOCKET) {
                        /* print client info */
                        printf("Server: accept connection from client (%s) port %d\n",
                        inet_ntoa(lsocket->remoteSockAddr.sin_addr),new_socket->remoteSockAddr.sin_port);
                  }
      //      }
            
      //}
            
  return new_socket;
}


int socketSend(void * soc, const void *msg, const int msgSize)
{
  int bytes_sent = -10;
 
      struct Socket *temp_soc = (struct Socket *)soc;

      /* check if soc is valid Socket */
      if (soc==NULL) {
            printf("error, soc is NULL\n");
            return -1000;
      }

      printf("sending [%s]\n",msg);
      
      /* calculate length of msg */
      int len = strlen(msg);
      
      /* send msg through sock stream if soc allows it */
      if(temp_soc->sType != BROKEN_SOCKET) {
            if((bytes_sent=send(temp_soc->sockFD,msg,len-1,0)) < 0) {
                  perror("error, send");
                  return NULL;
            }
      }
      else {
            printf("closing socket\n");
            socketClose(temp_soc);
            return -1002;
      }

  return bytes_sent;
}


int socketRecv(void * soc, void *buf, int bufSize)
{
  int bytes_received = -10;
 
      /* casting soc to struct Socket */
  struct Socket *temp_soc = (struct Socket *)soc;
      
      /* casting buf to string buffer */
      char *temp_buf = (char *)buf;
      
      /* check if soc is valid */
      if (soc==NULL) {
            printf("error, soc is NULL");
            socketClose(soc);
            return -1000;
      }
      
      /* recieve data through sock stream if socket allows it */
      if(temp_soc->sType != BROKEN_SOCKET) {
            if ((bytes_received=recv(temp_soc->sockFD,temp_buf,bufSize-1,0)) < 0) {
                  perror("error, recv");
                  return NULL;
            }
      }
      else {
            socketClose(temp_soc);
            return -1001;
      }
      
      if(temp_soc->sType == ACTIVE_SOCKET) {      
            /* print info */
            printf("received msg: [%s]\n",temp_buf);
            printf("%i bytes received\n",bytes_received);
      }
      
      
  return bytes_received;
}                                   

int socketClose(void *soc)
{
  int closed_result = -2;
      
      /* casting soc to struct Socket */
      struct Socket *temp_soc = (struct Socket *)soc;
      
      /* check if soc is valid */
      if (soc==NULL) {
            printf("soc is NULL");
            return -1001;
      }
      else
        closed_result = close(temp_soc->sockFD); /* close socket */

  return closed_result;
}

--------------------------------------------------------------------------------------------------------------

testServer.c and testClient.c

I'm pretty sure testClient.c is fine, and I was thinking of adding some sort of loop in testServer.c.

testServer.c :

int main(int argc, char* argv[])
{
      int port;

      /* buffer of 1024 bytes */
      char buf[1024];
      
      /* check if valid arguments are entered */
      if (argc!=2) {
            printf("usage: testServer 'port number'\n");
            exit(0);
      }
      
      /* convert argument to integer */
      port = atoi(argv[1]);
      
      printf("Server: calling createServerSocket (%d)\n",port);
      
      /* create server & accept connections */
      /* returning msg to client */
      char *good = "Ken is awesome.";
      
      int s = sizeof(buf);
                        
      void *ptr = createServerSocket(port);
      void *ptr2 = socketAccept(ptr);
      socketRecv(ptr2,buf,s);
      socketSend(ptr2,good,sizeof(good));

         //right now im just sending back a premade string (good) just to see if the connections are working. I still dunno how to              
         // implement the upper function i have in socket.c
      
  return 0;
}

 
testClient.c:

int main(int argc, char* argv[])
{
      int port;
      char buf[1024];

      int s = sizeof(buf);
      
      char *input = "The quick brown fox jumped over the lazy dog.";
      
      /* check if valid arguments are entered */
      if (argc!=3) {
            printf("usage: testClient 127.0.0.1 'port number'\n");
            exit(0);
      }
      
      /* convert argument to integer */
      port = atoi(argv[2]);
      
      printf("Client: calling createClientSocket('localhost',%d)\n",port);
      printf("Client: reading from standard input\n");
      printf("Client: read [%s]\n",input);
      
      void *ptr = createClientSocket(argv[1],port);
      socketSend(ptr,input,sizeof(input));
      socketRecv(ptr,buf,s);

  return 0;
}

wow that was pretty long heh. Basically, im stuck at how I can make the server socket handle multiple client connections and respond by changing the client sent strings to uppercase and sending it back.
kenbondAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

grg99Commented:
You need to spin off a thread after each accept,pass the thread the socket handle so it can communicate with the other end.  That's basically it.

0
kenbondAuthor Commented:
damn not it seems like recv isnt working that great. For example, I send "BYE" from the client. The server says it received "BY" and read only 2 bytes which should be 3.

or im gettin garbage characters at the end. i.e "The quick brown fox2|&#^$"
0
kenbondAuthor Commented:
^ figured that part out, but i still need to get uppercase working
0
grg99Commented:
sizeof(  whatever ) is wrong, it's always going to send the full array.

you need to get the actual string length with strlen( input ).



0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.