典型C/S模式___多进程实现

版权声明:私藏源代码是违反人性的罪恶行为!博客转载无需告知,学无止境。 https://blog.csdn.net/qq_41822235/article/details/84576541

一、思路

server进程通过accept()接收了一个连接请求。然后,子进程将作为“种籽”的server方插口关闭,而使用新的插口与client进程通信并为之提供服务。而父进程则把新的插口关闭,并再一次调用accept(),通过“种籽”插口来接收新的连接请求。

子进程注意事项有:父进程及时处理僵死的子进程,子进程运行结束就退出,不要产生一大堆后代······

二、编程实现

2.1 服务器端

#include<stdio.h>
#include<string.h>
#include<sys/socket.h> //socket() bind() listen() accept() 
#include<arpa/inet.h> //htons()
#include<netinet/in.h> //inet_addr()
#include<signal.h> //signal()
#include<stdlib.h> //exit()
#include<assert.h> //assert()

void conn(int c)    //供子进程使用
{
    while(1)
    {
	    char buf[128] = {'\0'};
	    int n = recv(c, buf, 127, 0);
	    if(n <= 0)
	    {
	        close(c);
	        break;
	    }
	    printf("%d: %s\n", c, buf);
	    char ack[5]={"OK"};
	    send(c, ack, strlen(ack), 0);
    }
}

//处理僵死的子进程
void zombie(int sign)
{
    wait(NULL);
}

int main()
{
    signal(SIGCHLD, zombie);
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    assert(-1 != sockfd);

    struct sockaddr_in ser, cli;
    ser.sin_family = AF_INET;
    ser.sin_port = htons(6000);
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");

    int res = bind(sockfd, (struct sockaddr*)&ser, sizeof(ser));
    assert(-1 != res);

    listen(sockfd, 5);

    while(1)
    {
	    int len = sizeof(cli);
	    int c = accept(sockfd, (struct sockaddr*)&cli, &len);
	    if( c < 0)
	    {
	        printf("Link Error\n");
	        continue;
	    }
	    pid_t n = fork();
	    if(0 == n) //子进程部分
	    {
	        close(sockfd);
	        conn(c);
	        exit(0); //结束子进程 否则子进程会产生很多后代
	    }else
	    {
	        close(c);
	    }
    }
    close(sockfd);
}

2.2 客户端

#include<stdio.h> //printf()
#include<assert.h> //assert()
#include<sys/socket.h> //socket()connect()recv()send()
#include<netinet/in.h> //inet_addr()
#include<arpa/inet.h> //htons()
#include<string.h> //strlen()
int main()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    assert(-1 != sockfd);
    
    struct sockaddr_in ser;
    ser.sin_family = AF_INET;
    ser.sin_port = htons(6000);
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    int res = connect(sockfd, (struct sockaddr*)&ser, sizeof(ser));
    while(1)
    {
        printf("please input: ");
        fflush(stdout);
        char buf[128] = {'\0'};
        scanf("%s", buf);
        char s1[30] = "client is terminated!";
        if(0 == strcmp(buf, "end"))
        {
            send(sockfd, s1, strlen(s1), 0);
            break;
        }else
        {
            send(sockfd, buf, strlen(buf), 0);
            char s2[128] = {'\0'};
            recv(sockfd, s2, 127, 0);
            printf("%d: %s\n", sockfd, s2);
        }
    }
    close(sockfd);
}

2.3 验证结果

2.4 追问

 我还是不清楚为什么服务器端会有两个套接字。这个先搁置,以后就会知道的。

猜你喜欢

转载自blog.csdn.net/qq_41822235/article/details/84576541