?
Solved

server socket able to accept multiple client connections

Posted on 2004-11-15
4
Medium Priority
?
542 Views
Last Modified: 2010-08-05
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.
0
Comment
Question by:kenbond
  • 2
  • 2
4 Comments
 
LVL 22

Expert Comment

by:grg99
ID: 12589708
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
 

Author Comment

by:kenbond
ID: 12589996
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
 

Author Comment

by:kenbond
ID: 12590055
^ figured that part out, but i still need to get uppercase working
0
 
LVL 22

Accepted Solution

by:
grg99 earned 500 total points
ID: 12590199
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

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
Suggested Courses

862 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question