1. 程式人生 > >典型C/S模式___多程序實現

典型C/S模式___多程序實現

一、思路

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 追問

 我還是不清楚為什麼伺服器端會有兩個套接字。這個先擱置,以後就會知道的。