2013-05-01 151 views
1

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

服务器:

#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; 
} 

回答

0

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 char * name;} int search_addr(char address [],int * des) char * name;} char * int j; char temp_addr [100]; strcpy(temp_addr,address); strtok_r(temp_addr,“”,& name); 对于(j = 0;Ĵ<客户端; 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); 

}

服务器发送新的客户端连接的ip地址和每个几分钟 192.168.12.61客户端1 进入味精 你好

2

这是你的修改服务器代码使用来处理多个客户端叉

#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; 
}