• 【并发服务器系列】1 停等模型


    we'll create a concurrent server program with some kind of message handling functions. 

    But first, let's look at some easy example. Then step by step , we create more and more complex programs.


    chat.h
    #ifndef __CHAT_H
    #define __CHAT_H

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

    #include <stdio.h>  
    #include <time.h> 
    #include <string.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <signal.h>

    //for inet_pton
    #include <arpa/inet.h> 

    //for waitpid
    #include <sys/types.h>
    #include <sys/wait.h>    

    #define SA struct sockaddr

    #define SERVER_PORT 54321

    #define PROTOL_TYPE  0xE3
    #define    OP_MESSAGE 0x4E

    const short MAX_MSG_LENGTH = 512;

    struct Message_Head
    {
        char protol_type;        
        char msg_type ;    
        size_t msg_length;
        int msg_size;
        //this sort will make the msg lager than it should
        Message_Head()
        {
            protol_type = PROTOL_TYPE;
            msg_type = OP_MESSAGE;        
            msg_length = 0;
            msg_size = 3;//?
        };
            
    };


    struct Message
    {    
        Message_Head msg_head;
        char msg_content[MAX_MSG_LENGTH];
        
        Message()
        {        
            memset(msg_content, 0sizeof(msg_content) );
        };
        
    };

    my_sock_api.cpp
    #include "chat.h"

    #define LISTENQ 10

    int sock_init(int &sockfd ,struct sockaddr_in &servaddr, uint16_t server_port)
    {
        
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(server_port);
        return sockfd;
    }
    int sock_server_init(int &listenfd , uint16_t server_port)
    {
        struct sockaddr_in servaddr;
        sock_init(listenfd, servaddr , server_port);        
        
        if(bind(listenfd, (SA*)&servaddr, sizeof(servaddr)) < 0)
        {
            perror("bind");
            return -1;
        }
        listen(listenfd, LISTENQ);
        return listenfd;
    }

    int sock_client_init(const char*ipaddress, uint16_t server_port)
    {
        int sockfd ;
        struct sockaddr_in servaddr;
        sock_init(sockfd, servaddr, server_port);    
        
        inet_pton(AF_INET, ipaddress, &servaddr.sin_addr);

        if(0 != connect(sockfd, (SA *) &servaddr, sizeof(servaddr)))
        {
            perror("connect");
            return -1;
        }
        return sockfd;    

    chat_server.cpp
    #include "chat.h"

    int listenfd, connfd;
    extern int sock_server_init(int &listenfd , uint16_t server_port);

    void err_sys(const char *error_string)
    {
        printf("%s\n", error_string);    
    }

    extern void p_read_from_p(int clientfd);
    extern int p_write_to_p(int clientfd, const char *msg);

    void sig_chld(int signo)
    {
        pid_t pid;
        int stat;
        while( (pid = waitpid(-1, &stat, WNOHANG)) > 0 )
        {
            printf("client %d terminated \n", pid);
        }
        return;
    }

    void chat_server()
    {
        printf("chat server start\n");
        void sig_chld(int);
        pid_t childpid;
        socklen_t clilen;
        struct sockaddr_in cliaddr ;
        
        if(sock_server_init(listenfd,(uint16_t) SERVER_PORT) < 0)
        {        
            return ;
        }
        
        signal(SIGCHLD, sig_chld);
        
        char buf[200] = {0};
        
        for(;;)
        {
            clilen = sizeof(cliaddr);
            if((connfd = accept(listenfd, (SA*)&cliaddr, &clilen )) < 0)
            {
                if(errno == EINTR)
                    continue;
                else
                    err_sys("accept error");
            }
            printf("incoming connection from IP: %s Port: %d\n"
                   inet_ntop(AF_INET, &cliaddr.sin_addr, buf, sizeof(buf)), 
                   ntohs(cliaddr.sin_port));        
            p_read_from_p(connfd);
            p_write_to_p(connfd, "hi , this is server");
            close(connfd);
        }//for

    clientProcesser.cpp
    #include "chat.h"

    void p_read_from_p(int clientfd)
    {
        if(0 == clientfd)
            return ;
            
        Message msg_receive;
        int read_size = 0;//fd read_size    
        if(( read_size = read(clientfd, &msg_receive.msg_head, sizeof(msg_receive.msg_head))) == 0)
        {
            return;//connection closed by other end
        }
        
        if(( read_size = read(clientfd, &msg_receive.msg_content, msg_receive.msg_head.msg_length)) == 0)
        {
            return;//connection closed by other end
        }
        printf(" ----> receive msg_content:\t %s \n", msg_receive.msg_content);
        fflush(stdout);
        
    }
    int p_write_to_p(int clientfd, const char *msg)
    {
        size_t slen = strlen(msg);
        if(slen > MAX_MSG_LENGTH || 0 == slen)
            return -1;
            
        Message msg_send;
        msg_send.msg_head.msg_length = slen;
        strncpy(msg_send.msg_content , msg, slen);
                
        int wn = write(clientfd, &msg_send ,sizeof(msg_send.msg_head)+slen );
        printf(" write finished msg:\t %s  \n",msg );

    chat_client.cpp
    #include "chat.h"

    extern int sock_client_init(const char*ipaddress, uint16_t server_port);

    extern int p_write_to_p(int clientfd, const char *msg);
    extern void p_read_from_p(int clientfd);

    void chat_client(const char* linkin_ip)
    {
        printf("chat client start %s \n", linkin_ip);
        int clientfd = sock_client_init(linkin_ip, SERVER_PORT);    
        if(clientfd < 0 )
        {        
            return ;
        }
        p_write_to_p(clientfd, "hello, this is client");
        p_read_from_p(clientfd);

    chatmain.cpp
    #include "chat.h"

    void usage()
    {
        printf("./chat& \t first chat login , in order to receive other client's message \n\
        ./chat endpoint_ip_address \t start a client to chat with endpoint_ip_address \n");
    }

    extern void chat_server();
    extern void chat_client(const char *linkin_ip);

    int main(int argc, char **argv)
    {
        if(argc == 1)
        {
            chat_server();
        }
        else if(argc == 2)
        {        
            chat_client(argv[1]);
        }    
        else
        {
            usage();
        }
        return 0;
    }


    g++ chatmain.cpp chat_server.cpp chat_client.cpp my_sock_api.cpp clientProcesser.cpp -o chat

  • 相关阅读:
    两台虚拟机(不同电脑)通信
    虚拟机使用网络助手
    strcpy_s
    线程创建几种方法
    JavaWeb——EL详解
    JavaWeb_EL语法
    JavaWeb_JavaBean
    JavaWeb_HttpSession之验证码
    JavaWeb_HttpSession之表单的重复提交
    JavaWeb——相对路径和绝对路径
  • 原文地址:https://www.cnblogs.com/no7dw/p/2675150.html
Copyright © 2020-2023  润新知