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

标签 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);


}

最佳答案

两个客户端相互交谈的一种方式是:accept 在您 fork 子进程之前两次,因此两个进程相互了解。

让服务器使用客户端 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

关于c - 如何使用 fork() 通过服务器连接两个客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27314288/

相关文章:

C 中的 char 数组并进行比较

java - java.net.Socket 是否检测客户端超时?

python 错误: 'module' object has no attribute 'AF_UNIX'

C++ mktime 更改我的 tm_struct 的值

c - 如何在C中不使用递归实现二叉搜索树的删除函数?

c++ - 为什么套接字(AF_INET、SOCK_DGRAM、IPPROTO_UDP)会失败?

c - IF 语句中没有 fork

c - 调用fork时是否复制线程?

c - 使用C将exec进程发送到后台?

c - 初始化指针数组