【并发服务器系列】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

原文地址:https://www.cnblogs.com/no7dw/p/2675150.html