具有多个客户端C / unix的简单TCP服务器

时间:2013-05-01 23:36:57

标签: c unix tcp network-programming client-server

我在理解套接字编程时遇到问题,需要一些帮助。我想修改我编写的服务器代码以接受3个客户端。我知道我想为每个客户端使用一个fork,但我不知道如何在我的代码中实现它。这是我为一个客户编写的原始代码。任何帮助将不胜感激。

服务器:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

void error(const char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{
     int sockfd, newsockfd, portno;
     socklen_t clilen;
     char buffer[256];
     struct sockaddr_in serv_addr, cli_addr;
     int n;
     if (argc < 2) {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0) 
        error("ERROR opening socket");
     bzero((char *) &serv_addr, sizeof(serv_addr));
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0) 
              error("ERROR on binding");
     listen(sockfd,5);
     clilen = sizeof(cli_addr);
     newsockfd = accept(sockfd, 
                 (struct sockaddr *) &cli_addr, 
                 &clilen);
     if (newsockfd < 0) 
          error("ERROR on accept");
     bzero(buffer,256);
     n = read(newsockfd,buffer,255);
     if (n < 0) error("ERROR reading from socket");
     printf("Here is the message: %s\n",buffer);
     n = write(newsockfd,"I got your message",18);
     if (n < 0) error("ERROR writing to socket");
     close(newsockfd);
     close(sockfd);
     return 0; 
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 

void error(const char *msg)
{
    perror(msg);
    exit(0);
}

int main(int argc, char *argv[])
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;

    char buffer[256];
    if (argc < 3) {
       fprintf(stderr,"usage %s hostname port\n", argv[0]);
       exit(0);
    }
    portno = atoi(argv[2]);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) 
        error("ERROR opening socket");
    server = gethostbyname(argv[1]);
    if (server == NULL) {
        fprintf(stderr,"ERROR, no such host\n");
        exit(0);
    }
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr, 
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);
    serv_addr.sin_port = htons(portno);
    //printf("h_addr: %s\n", inet_ntoa(serv_addr.sin_addr));
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
        error("ERROR connecting");
    printf("Please enter the message: ");
    bzero(buffer,256);
    fgets(buffer,255,stdin);
    n = write(sockfd,buffer,strlen(buffer));
    if (n < 0) 
         error("ERROR writing to socket");
    bzero(buffer,256);
    n = read(sockfd,buffer,255);
    if (n < 0) 
         error("ERROR reading from socket");
    printf("%s\n",buffer);
    close(sockfd);
    return 0;
}

2 个答案:

答案 0 :(得分:4)

这是您使用fork

处理多个客户端的修改后的服务器代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

void error(const char *msg) {
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[]) {
    int sockfd, newsockfd, portno;
    socklen_t clilen;
    char buffer[256];
    struct sockaddr_in serv_addr, cli_addr;
    int n;
    if (argc < 2) {
         fprintf(stderr, "ERROR, no port provided\n");
         exit(1);
    }
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
         error("ERROR opening socket");
    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = atoi(argv[1]);
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
        error("ERROR on binding");
    listen(sockfd, 5);
    clilen = sizeof(cli_addr);
    //Below code is modified to handle multiple clients using fork
    //------------------------------------------------------------------
    int pid;
    while (1) {
         newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
         if (newsockfd < 0)
                error("ERROR on accept");
         //fork new process
         pid = fork();
         if (pid < 0) {
              error("ERROR in new process creation");
         }
         if (pid == 0) {
            //child process
            close(sockfd);
            //do whatever you want
            bzero(buffer, 256);
            n = read(newsockfd, buffer, 255);
            if (n < 0)
                error("ERROR reading from socket");
            printf("Here is the message: %s\n", buffer);
            n = write(newsockfd, "I got your message", 18);
            if (n < 0)
                 error("ERROR writing to socket");
            close(newsockfd);
          } else {
             //parent process
             close(newsockfd);
          }
    }
    //-------------------------------------------------------------------
   return 0;
}

答案 1 :(得分:-1)

Server.c

         #define RUNNING_DIR     "/tmp "
        define LOCK_FILE       "exampled.lock"
        #define LOG_FILE        "exampled.log"
        #include <fcntl.h>
   #include <signal.h>
     #include <unistd.h>
     #include <stdlib.h>
     #include <sys/types.h>
   #include  <sys/socket.h>
   #include  <stdio.h>
  #include  <netinet/in.h>
     #include  <sys/time.h>
      #include  <sys/ioctl.h>
    #include  <unistd.h>
    #include <string.h>
  #include <arpa/inet.h>
       #include <errno.h>
 #include <time.h>
  #include <string.h>
        #define MAXCLIENT 100
        #define TRUE 1
        #define FALSE 0
       #define MINUTE 5
      struct Client
      {
    char name[256];
char *clientAddr;
int fd;
     };
    int client;
      int i;
    int minute;
    struct Client p[100];
     void remove_client(int); 
     int search_addr(char [],int *);
     void log_message(filename,message)
char *filename;
char *message;
      {
FILE *logfile;
logfile=fopen(filename,"a");
if(!logfile) return;
fprintf(logfile,"%s\n",message);
fclose(logfile);
    }

      void catch_int(sig)
int sig;
  {
log_message(LOG_FILE,strsignal(sig));
     }

    void daemonize()
   {
int i,lfp,lfp1;
char str[10];
    signal(SIGINT, catch_int);
for ( i=0;i<65;i++)
{
    if ( i!=32 && i!=33 )
        if (signal(i, SIG_IGN) != SIG_IGN)
            signal(i, catch_int);
}
if(getppid()==1) return; /*    already a daemon */
i=fork();
if (i<0) exit(1); /*    fork error */
if (i>0) exit(0); /*    parent exits */
/*    child (daemon) continues */
setsid(); /*    obtain a new process group */
for (i=getdtablesize();i>=0;--i) close(i); /*    close all descriptors */
i=open("/dev/null",O_RDWR); dup(i); dup(i); /*    handle standart I/O */
umask(027); /*    set newly created file permissions */
chdir(RUNNING_DIR); /*    change running directory */
lfp=open(LOCK_FILE,O_RDWR|O_CREAT,0640);
lfp1=open(LOG_FILE,O_RDWR|O_CREAT,0640);
if (lfp<0) exit(1); /*    can not open */
if (lockf(lfp,F_TLOCK,0)<0) exit(0); /*    can not lock */
/*    first instance continues */
sprintf(str,"%d\n",getpid());
write(lfp,str,strlen(str)); /*    record pid to lockfile */
   }
       int main()
         {
     daemonize();
   time_t rawtime;
  struct tm *info;
      time(&rawtime);
     info = localtime(&rawtime );
     minute=MINUTE + info->tm_min;
      int server_sockfd, client_sockfd;
     int server_len, client_len;
      struct sockaddr_in server_address;
       struct sockaddr_in client_address;
      int result;
        fd_set readfds, testfds;
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(5000);
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
listen(server_sockfd, 5);
FD_ZERO(&readfds);
FD_SET(server_sockfd, &readfds);
while(1) {
    char ch;
    int fd;
    int nread;
    testfds = readfds;
    result = select(FD_SETSIZE,&testfds,NULL,NULL,NULL);
    if(result < 1) {
        perror("server5");
        exit(1);
    }
    for(fd = 0; fd < FD_SETSIZE; fd++) {
        time(&rawtime);
        info = localtime(&rawtime );
        if(FD_ISSET(fd,&testfds)) {
            if(fd == server_sockfd) {
                int j=0;
                char Clients[1096];
                memset( Clients, '\0', sizeof(Clients) );
                client_len = sizeof(client_address);
                client_sockfd = accept(server_sockfd,
                        (struct sockaddr          *)&client_address, &client_len);
                client++;
                char *sAddress = inet_ntoa(client_address.sin_addr);
                p[i].clientAddr=strdup(sAddress);
                sprintf(p[i].name,"client%d",client);
                p[i].fd=client_sockfd;
                for (j =0; j < client; j++)
                {
                    strcat(Clients,p[j].clientAddr);
                    strcat(Clients," ");
                    strcat(Clients,p[j].name); 
                    strcat(Clients,"\n");  
                }
                for ( j=0; j < client ; j++)
                {
                    send(p[j].fd,Clients,strlen(Clients),0);
                }
                i++;
                FD_SET(client_sockfd, &readfds);
            }
            else {
                ioctl(fd, FIONREAD, &nread);
                if(nread == 0) {
                    close(fd);
                    remove_client(fd);
                    FD_CLR(fd, &readfds);
                }
                else {
                    char addr[100];
                    char *msg;
                    char sucess[]="Message from Ip Address:";
                    int n;
                    int des=0;
                    int found;
                    n=recv(fd,addr,sizeof(addr),0);
                    addr[n]='\0';
                    strtok_r (addr, "\n", &msg);
                    found=search_addr(addr,&des);
                    if ( found )
                    {
                        strcat(sucess,addr); 
                        send(fd,"Message Has been  
                                sucessfully sended\n",36,0); 
                        strcat(sucess,"\n");
                        strcat(sucess,msg);
                        send(des,sucess,strlen(sucess),0); 
                    }
                    else
                    {
                        send(fd,"Message Sending    Failed..\n",27,0);
                    } 
                    sleep(5);
                }

            }
        }
        if ( minute == info->tm_min)
        {
            int j=0;
            char Clients[1096];
            memset( Clients, '\0', sizeof(Clients) );
            sprintf(Clients,"Now Currently Available ip:\n");
            for (j =0; j < client; j++)
            {
                strcat(Clients,p[j].clientAddr);
                strcat(Clients," ");
                strcat(Clients,p[j].name); 
                strcat(Clients,"\n");  
            }
            for ( j=0; j < client ; j++)
            {
                send(p[j].fd,Clients,strlen(Clients),0);
            }
            minute=minute+MINUTE;
        }
    }
}

}

         void remove_client(int fd)
      {
int j=0;
int pos;
for  ( j=0; j< client ; j++)
{
    if ( p[j].fd == fd )
    {
        pos=j;
        break;         
    }            
}
for ( j=pos+1 ; j < client ; j++)
{
    sscanf( p[j].name, "%s",p[pos].name);
    p[pos].clientAddr=p[j].clientAddr;
    p[pos].fd=p[j].fd;
    pos++;

}
client--;
i--;

}                   int search_addr(char address [],int * des)                  {             char * name;              int j;             char temp_addr [100];              的strcpy(TEMP_ADDR,地址);              strtok_r(temp_addr,“”,&amp; name);        for(j = 0; j&lt; client; j ++)         {

         if ( (strcmp(temp_addr,p[j].clientAddr)==0) &&          (strcmp(name,p[j].name)==0))
    {
        *des=p[j].fd;
        return TRUE;
    }
}
return FALSE;

}

Client.c

 #include <stdlib.h>
    #include <sys/socket.h>
  #include <sys/types.h>
   #include <netinet/in.h>
   #include <netdb.h>
 #include <stdio.h>
   #include <string.h>
   #include <stdlib.h>
   #include <unistd.h>
      #include <errno.h>
        #include <arpa/inet.h> 
      // #define  SERVERIP "192.168.12.61"
       #define  PORT 5000
    #include <setjmp.h>
    #define MAXSLEEP 128
     int main(int argc, char *argv[])
        {
int Response=1;
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr; 
jmp_buf env;
if(argc != 2)
{
    printf("\n Usage: %s <ip of server> \n",argv[0]);
    return 1;
} 
memset(recvBuff, '0',sizeof(recvBuff));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
    printf("\n Error : Could not create socket \n");
    return 1;
} 

memset(&serv_addr, '0', sizeof(serv_addr)); 

serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT); 

if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
{
    printf("\n inet_pton error occured\n");
    return 1;
} 
setjmp(env);
    if (connect_retry ( sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr) )< 0 )
{
    printf("Time Limited Exceeded....\n ");
    return 0;

} 
for (;;) {
    char str[100];
    char addr[100];
    if ( Response == 1 )
    {
        int z = recv(sockfd,recvBuff,sizeof(recvBuff),0); //MSG_DONTWAIT
        if ( z == -1 )
        {
        }
        else if ( z == 0 )
        {
            printf("Server Failed ....\n");
            longjmp(env, 2);
            break;
        }
        else
        {
            recvBuff[z] = 0;
            printf("'%s'",recvBuff);
            sleep(1);
        }
    }
    else
    {
        int z = recv(sockfd,recvBuff,sizeof(recvBuff),MSG_DONTWAIT); //MSG_DONTWAIT
        if ( z == -1 )
        {
        }
        else if ( z == 0 )
        {
            printf("Server Failed...\n");
            longjmp(env, 2);
            break;
        }
        else
        {
            recvBuff[z] = 0;
            printf("'%s'",recvBuff);
            sleep(1);
        }

    }
    fd_set rfdset;
    FD_ZERO(&rfdset);
    struct  timeval tv;
    tv.tv_sec = 10;
    tv.tv_usec = 0;
    FD_SET(STDIN_FILENO, &rfdset);
    int bReady = select(STDIN_FILENO+1,&rfdset,NULL,NULL,&tv);
    if (bReady > 0)
    {
        //  printf("Chat with Client Address: \n");
        if( fgets (addr, 4096, stdin)!=NULL ) {
        }
        printf("Enter Message:\n");
        if( fgets (str, 4096, stdin)!=NULL ) {
        }
        strcat(addr,str);
        send(sockfd,addr,strlen(addr),0);
    }
    Response=0;
}
return 0;

}

int
     connect_retry(int sockfd, const struct sockaddr *addr, socklen_t alen)
      {
int nsec;

/*
 *          * Try to connect with exponential backoff.
 *                   */
for (nsec = 1; nsec <= MAXSLEEP; nsec <<= 1) {
    if (connect(sockfd, addr, alen) == 0) {
        /*
         *                          * Connection accepted.
         *                                                   */
        return(0);
    }

    /*
     *                  * Delay before trying again.
     *                                   */
    printf("Waiting For Server....\n");
    if (nsec <= MAXSLEEP/2)
        sleep(nsec);
}
return(-1);

}

服务器发送新客户端连接的ipaddress并且每隔几分钟  192.168.12.61 client1   输入信息    你好