采用fork实现多客户server端

          一般的socket通信的过程是:服务器在接受来自客户的一个新连接时,会创建出一个新的套接字,而已有的监听套接字将继续接受来自客户端的请求并将它们放入队列中等待处理(调用accept处理)。

       由accept获得的套接字描述符在主进程调用fork时,可以被子进程共享,因此,如果accept之后,在子进程中处理连接,在父进程中关闭套接字描述符,就可以处理一个客户端连接了。重复上述的过程,就用fork实现了server端的多客户编程。

      需要注意的是主进程在创建了子进程后,并没有调用wait方法来等待它们的完成,这样容易出现僵尸进程,需要在主进程中设置忽略SIGCHLD信号以避免出现僵尸进程。

     下面采用Linux程序设计上的例子来说明这个过程:

        服务端

      

/*  This program, server4.c, begins in similar vein to our last server,
    with the notable addition of an include for the signal.h header file.
    The variables and the procedure of creating and naming a socket are the same.  */

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>

int main()
{
    int server_sockfd, client_sockfd;
    int server_len, client_len;
    struct sockaddr_in server_address;
    struct sockaddr_in client_address;

    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(9734);
    server_len = sizeof(server_address);
    bind(server_sockfd, (struct sockaddr *)&server_address, server_len);

/*  Create a connection queue, ignore child exit details and wait for clients.  */

    listen(server_sockfd, 5);

    signal(SIGCHLD, SIG_IGN);

    while(1) {
        char ch;

        printf("server waiting\n");

/*  Accept connection.  */

        client_len = sizeof(client_address);
        client_sockfd = accept(server_sockfd, 
            (struct sockaddr *)&client_address, &client_len);

/*  Fork to create a process for this client and perform a test to see
    whether we're the parent or the child.  */

        if(fork() == 0) {

/*  If we're the child, we can now read/write to the client on client_sockfd.
    The five second delay is just for this demonstration.  */

            read(client_sockfd, &ch, 1);
            sleep(5);
            ch++;
            write(client_sockfd, &ch, 1);
            close(client_sockfd);
            exit(0);
        }

/*  Otherwise, we must be the parent and our work for this client is finished.  */

        else {
            close(client_sockfd);
        }
    }
}


客户端:

/*  Make the necessary includes and set up the variables.  */

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

int main()
{
    int sockfd;
    int len;
    struct sockaddr_in address;
    int result;
    char ch = 'A';

/*  Create a socket for the client.  */

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

/*  Name the socket, as agreed with the server.  */

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr("127.0.0.1");
    address.sin_port = htons(9734);
    len = sizeof(address);

/*  Now connect our socket to the server's socket.  */

    result = connect(sockfd, (struct sockaddr *)&address, len);

    if(result == -1) {
        perror("oops: client3");
        exit(1);
    }

/*  We can now read/write via sockfd.  */

    write(sockfd, &ch, 1);
    read(sockfd, &ch, 1);
    printf("char from server = %c\n", ch);
    close(sockfd);
    exit(0);
}

      服务器程序将会创建新的子进程来处理客户连接。样例实现了客户端向服务端写入一个字符后,服务端读取该字符并协会该字符的下一个字符。例如客户端写入A,服务端写回B,客户端显示服务端写会的B。

   

在 C 语言中,使用 fork() 函数可以创建一个新的子进程,并在子进程中运行一些指定的代码。我们可以利用这个特性来实现一个多进程计算从 1 加到 100 的程序。 下面是一个示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #define MAX_NUM 100 int sum = 0; // 全局变量,用于统计加和结果 void calc(int start, int end) { int i; for (i = start; i <= end; i++) { sum += i; } } int main(void) { int i, pid, status, step = MAX_NUM / 2; // step 表示每个子进程计算的区间大小 for (i = 0; i < 2; i++) { pid = fork(); // 创建新的子进程 if (pid == -1) { // 创建失败 printf("Failed to create child process.\n"); exit(1); } else if (pid == 0) { // 子进程 int start = i * step + 1; int end = (i + 1) * step; calc(start, end); exit(0); // 子进程结束 } } // 等待子进程结束 for (i = 0; i < 2; i++) { wait(&status); } printf("The sum of 1 to %d is %d\n", MAX_NUM, sum); return 0; } ``` 上述代码中,我们首先定义了一个全局变量 `sum`,用于存储加和的结果。然后使用一个循环来创建两个子进程,每个子进程计算从 `start` 到 `end` 的区间的和。父进程等待两个子进程结束后,输出最终的加和结果。 需要注意的是,子进程需要调用 `exit()` 函数来结束自己的运行,否则它会继续执行父进程的代码。另外,在使用 `fork()` 函数时,需要进行错误处理。如果返回值为 -1,则表示创建子进程失败,此时应该退出程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值