如何使用fork()通过服务器连接两个客户端

时间:2014-12-05 10:54:24

标签: c sockets fork

我想创建一个邮件服务器。服务器一次连接两个客户端。当连接两个客户端时,每个客户端可以替代地输入文本并读取由另一个客户端写入的文本。服务器将在两个客户端中显示以下消息:

client 1 said : .......
what is your answer?
.....
....

我正在努力弄清楚如何在两个客户端之间建立连接我所能做的就是在服务器和客户端之间进行通信(发送和接收文本)但我不知道如何通过其他客户端连接服务器(我必须在此任务中使用FORK())。 任何帮助将不胜感激

这里是服务器的代码:

#include  "unistd.h"
#include "errno.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "netdb.h"

#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "strings.h"
#include "sys/wait.h"


    //Function Prototypes
    void myabort(char *);

    //Some Global Variables
    int serverport = 3000;
    char * eptr = NULL;
    int listen_socket, client_socket;
    struct sockaddr_in Server_Address, Client_Address;
    int result,i;
    socklen_t csize;
    pid_t processid;
    int childcount = 0;


    //main()
    int
    main(int argc, char **argv){

    char buf[100];
    char tmp[100];
          char * ptr;
         int n, sent, length;

        //Step 0: Process Command Line
         if (argc > 2){
             myabort("Usage: server ");
         }
        if (argc == 2){
             serverport =  (int) strtol(argv[1], &eptr, 10);
               if (*eptr != '\0') myabort("Invalid Port Number!");
          }

    //Step 1: Create a socket
          listen_socket = socket(PF_INET, SOCK_STREAM, 0);
          if (listen_socket == -1) myabort("socket()");


      //Step 2: Setup Address structure
         bzero(&Server_Address, sizeof(Server_Address));
          Server_Address.sin_family = AF_INET;
          Server_Address.sin_port = htons(serverport);
          Server_Address.sin_addr.s_addr = INADDR_ANY;


     //Step 3: Bind the socket to the port
          result = bind(listen_socket, (struct sockaddr *) &Server_Address, sizeof(Server_Address));
          if (result == -1) myabort("bind()");

    //Step 4:Listen to the socket
          result = listen(listen_socket, 1);
         if (result == -1) myabort("listen()");



    printf("\nThe forkserver :%d\n",ntohs(Server_Address.sin_port));
        fflush(stdout);
     //Step 5: Setup an infinite loop to make connections
        while(1){


    //Accept a Connection
             csize = sizeof(Client_Address);
               client_socket = accept( listen_socket,(struct sockaddr *) &Client_Address,&csize);
            if (client_socket == -1) myabort("accept()");

              printf( "\nClient Accepted!\n" );


            //fork this process into a child and parent
              processid = fork();

               //Check the return value given by fork(), if negative then error,
              //if 0 then it is the child.
              if ( processid == -1){
                  myabort("fork()");
            }else if (processid == 0){
                  /*Child Process*/

                close(listen_socket);
                  //loop until client closes
                 while (1){



                    //read string from client
                    bzero(&buf, sizeof(buf));
                    do{
                        bzero(&tmp, sizeof(tmp));
                        n = read(client_socket,(char *) &tmp, 100);
                        //cout << "server:  " << tmp;
                        tmp[n] = '\0';
                        if (n == -1) myabort("read()");
                        if (n == 0) break;
                        strncat(buf, tmp, n-1);
                        buf[n-1] = ' ';
                    } while (tmp[n-1] != '\n');

                    buf[ strlen(buf) ] = '\n';

                printf( "From client: %s",buf);

                    if (n == 0) break;


                     //write string back to client
                    sent = 0;
                    ptr = buf;
                      length = strlen(buf);

                    //the vowels in the message are converted into upper case.
                    for( i = 0; ptr[ i ]; i++)
                    {
                        if( ptr[i]=='a' ||  ptr[i]=='e' ||  ptr[i]=='i' || ptr[i]=='o' ||  ptr[i]=='u' )
                                 ptr[ i ] = toupper(  ptr[ i ] );
                        else
                             ptr[ i ] = ptr[ i ] ;

                    }   


                    printf( "To client: %s",ptr);
                    while (sent < length ){
                        n = write(client_socket, ptr, strlen(ptr) );
                        if ( n == -1) myabort("write()");
                        sent += n;
                        ptr += n;
                    }
                }//end inner while

                close(client_socket);

                //Child exits
                exit(0);
             }


              //Parent Process

            printf("\nChild process spawned with id number:  %d",processid );
            //increment the number of children processes
            childcount++;
            while(childcount){
                processid = waitpid( (pid_t) - 1, NULL, WNOHANG );
                if (processid < 0) myabort("waitpid()");
                else if (processid == 0) break;
                 else childcount--;
            }   

        }
        close(listen_socket);

        exit(0);

    }


    void myabort(char * msg){
        printf("Error!:  %s" ,  msg);
        exit(1);
    }

客户:

#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "unistd.h"
#include "sys/socket.h"
#include "sys/types.h"
#include "netinet/in.h"
#include "strings.h"
#include "arpa/inet.h"

#define BUFFER    1024


main(int argc, char **argv)
{
    struct sockaddr_in serv;
    int sock;
    char in[BUFFER];
    char out[BUFFER];
    int len;


    if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }

    serv.sin_family = AF_INET;
    serv.sin_port = htons(atoi(argv[2]));
    serv.sin_addr.s_addr = inet_addr(argv[1]);
    bzero(&serv.sin_zero, 8);

    printf("\nThe TCPclient %d\n",ntohs(serv.sin_port));
        fflush(stdout);


    if((connect(sock, (struct sockaddr *)&serv, sizeof(struct sockaddr_in))) == -1)
    {
        perror("connect");
        exit(-1);
    }

    while(1)
    {
        printf("\nInput: ");

        fgets(in, BUFFER, stdin);
        send(sock, in, strlen(in), 0);


        len = recv(sock, out, BUFFER, 0);
        out[len] = '\0';
        printf("Output: %s\n", out);
    }

    close(sock);


}

3 个答案:

答案 0 :(得分:1)

两个客户端相互通信的一种方法是:accept两次在分叉子进程之前,因此两个进程都相互了解。

让服务器使用客户端B的UNIX域套接字文件描述符发送到A,而A到B,服务器知道两个客户端的fd。检查这是否为unix域套接字(Sending file descriptor over UNIX domain socket, and select()

使用服务器作为中间人:

A write to server
Server write to B whild B read from server
B write to server while server read from B
Server write to A while A should read from server

答案 1 :(得分:0)

我认为您必须通过服务器注册您的客户端并将其套接字描述符存储在某种类型的数组中。每个客户端都应具有唯一标识符。还要指定某种协议,其中包含一些信息,如发送方,目的地(= client1或2)和消息。您的服务器可以处理邮件并将邮件路由到目的地。

协议可以是一个简单的协议,如

发送方|到|消息

例如

client-1 | client-2 |客户1的问候

您还可以使用某些xml或任何其他类型的数据结构

在服务器端。将消息提取为3个字符串部分 string-1:sender(client-1) string-2:destination(client-2) string 3:消息(来自客户端1的Hello

服务器可以将消息(即字符串-3)发送到客户端-2

答案 2 :(得分:0)

几天前我为同一场景编写了代码。不是仍然适当,但它工作得很好,并会给你一个良好的开端

服务器端代码: -

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<signal.h>
#include<sys/wait.h>


static void   sigchld_handler(int signo) {  
    pid_t PID;   
    int status;  

  do {  
     PID = waitpid(-1,&status,WNOHANG);  
      }   
  while ( PID != -1 );  

//重新启动处理程序

  signal(SIGCHLD,sigchld_handler);  

}

  int main(int argc ,char *argv[])
{ 
   int server_socket; 
    int client_socket , size_structure,read_size,binds;
    int *new_socket;
    struct sockaddr_in server, client ;
    server_socket = socket(AF_INET, SOCK_STREAM,0);
    char client_message[100]="";
     pid_t PID;                    /* Process ID */  

/ *   *为SIGCHLD设置信号处理程序:   * /
     信号(SIGCHLD,sigchld_handler);

    if(server_socket == -1)
    {  
        puts("socket has nt been created");
    }
    else 
        puts("socket has been created");

    //give values to the structure for server
 server.sin_family = AF_INET;
 server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(2225);

//step 3 bind karo 
binds = bind(server_socket,(struct sockaddr*)&server,sizeof(server));

if(binds<0)
    {
    perror("bind failed.Error");
    return 1;
    } 
    puts("SOcket has been binded to address");

//listen to incoming request

listen(server_socket,30); 
size_structure = sizeof(struct sockaddr_in);
FILE *fp;
fp =fopen("test.txt","w");

while (1)
    {

    client_socket = accept(server_socket,(struct sockaddr *)&client,(socklen_t*)&size_structure);
     if(client_socket<0)
        { 
            puts("client is nt connected");
        return 1;
        }
    else 
        puts("connection accepted");

    if((PID = fork())== -1)
        { 
            close(client_socket);
            continue;
        }

    else if(PID >0)
        {
        close(client_socket);
        continue;
        }

    setlinebuf(fp);

    while(( read_size=recv(client_socket,client_message,2000,0))>0)
        {

        puts(client_message);
            write(client_socket,client_message,sizeof(client_message));
        for(int i=0;i<500;i++)
            { 
            fwrite(client_message,1,sizeof(client_message),fp);
            } 
        if(PID==-1)
            {  
            exit(0);
            }
        memset(client_message,0,strlen(client_message));

        }

    if(read_size==-1)
        {
        puts("client disconnected");
        fflush(stdout);
        close(client_socket);
        exit(0);
        }
    else if(read_size == 0)
        { 
            printf("recveiving failed");
            }
    }



memset(client_message,0,strlen(client_message));
close(client_socket);
fclose(fp);
return 0;

}

客户代码: -

   #include<stdio.h>
   #include<sys/socket.h>
   #include<arpa/inet.h>
   #include<string.h>
 #include<sys/types.h>


 int main()
{

 struct sockaddr_in myaddr ,serveraddr;
 int sockid;
 sockid=socket(AF_INET,SOCK_STREAM,0);
 memset(&myaddr,'0',sizeof(myaddr));
 myaddr.sin_family=AF_INET;
 myaddr.sin_port=htons(8888);
 myaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
 if(sockid==-1)
 {
    perror("socket");
 }
 int len=sizeof(myaddr);
 if(connect(sockid,(const struct sockaddr*)&myaddr,len)==-1)
 {
    perror("connect");
 }
 fprintf(stdout,"Client Online....");
 char s[10000];


    //gets(s);
    //send(sockid,s,10000,0);
    recv(sockid,&s,10000,0);
    fprintf(stdout,"Server says....");
    puts(s);
    recv(sockid,&s,10000,0);
    fprintf(stdout,"Server says....");
    puts(s);

 sleep(10);  
 close(sockid);
 return 0;
}