linux——socket编程之多进程编程

创建进程:
Linux下的进程
在创建新进程时,要进行资源拷贝。Linux 有三种资源拷贝的方式:
1.共享:新老进程共享通用的资源。当共享资源时,两个进程共同用一个数据结构,不需要为新进程另建。
2.直接拷贝:将父进程的文件、文件系统、虚拟内存等结构直接拷贝到子进程中。子进程创建后,父子进程拥有相同的结构。
3.Copy on Write:拷贝虚拟内存页是相当困难和耗时的工作,所以能不拷贝就最好不 要拷贝,如果必须拷贝,也要尽可能地少拷贝。为此,Linux 采用了 Copy on Write 技术,把真正的虚拟内存拷贝推迟到两个进程中的任一个试图写虚拟页的时候。如 果某虚拟内存页上没有出现写的动作,父子进程就一直共享该页而不用拷贝。

多进程并发服务器的基本思路:
1建立连接
2服务器调用fork()产生新的子进程
3父进程关闭连接套接字,子进程关闭监听套接字
4子进程处理客户请求,父进程等待另一个客户连接


代码如下:

/*********************************************************************************
 *      Copyright:  (C) 2018 weirenqiu
 *                  All rights reserved.
 *
 *       Filename:  mul_pro_server.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(05/17/2018)
 *         Author:  weirenqiu <>
 *      ChangeLog:  1, Release initial version on "05/17/2018 03:55:18 PM"
 *                 
 ********************************************************************************/



/********************************************************************************
 *  Description:as a concurrent server,Each client opens a process, and the number of clients is equal to the number of child processes on the server.
 *   Input Args:
 *  Output Args:
 * Return Value:
********************************************************************************/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define BUF_SIZE 1024
void read_childproc(int sig); //childprocess destruction


int main (int argc, char **argv)
{       
      int serv_fd, clit_fd;
      struct sockaddr_in serv_addr, clit_addr;
      pid_t pid;
      struct sigaction act;
      socklen_t addr_sz;
      int str_len, state;
      char buf[BUF_SIZE];

     if (argc != 2) 
     {
         printf("Usage: %s  \n", argv[0]);
         exit(1);
     }

     act.sa_handler = read_childproc;
     sigemptyset(&act.sa_mask);
     act.sa_flags = 0;
     state = sigaction(SIGCHLD, &act, 0);//The registered child process terminates the event.
    //Initialize the socket
     if( (serv_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
         printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
         exit(0);
     }
     //Initialize
     memset(&serv_addr, 0, sizeof(serv_addr));
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//The IP address is set to INADDR_ANY,The system automatically gets the IP address
     serv_addr.sin_port = htons(atoi(argv[1]));
     
    //bind  the local address to the created socket.
     if( bind(serv_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1){
         printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
         exit(0);
     }

        //Start listening for client connections or not .
     if( listen(serv_fd, 10) == -1){
         printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
         exit(0);
     }
     printf("======waiting for client's request======\n");

     while (1)
     {      //Until there is a client connection.
         addr_sz = sizeof(clit_addr);
         if( (clit_fd=accept(serv_fd, (struct sockaddr*)&clit_addr,&addr_sz)) == -1){
             printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
             continue;
         }
         else
             puts("new client connected...");

         pid = fork(); // creat childprocess
             if(pid == -1)
             {
                 close(clit_fd);
                 continue;
             }
             if (pid == 0)
             {
                 close(serv_fd);
                 while((str_len = read(clit_fd, buf, BUF_SIZE)) != 0)
                     write(clit_fd, buf, str_len);

                 close(clit_fd);
                 puts("client disconnected...");
                 return 0;
             }
             else
                 close(clit_fd);
             }

           close(serv_fd);

            return 0;
            }
/* ----- End of main() ----- */
void read_childproc(int sig)
{
    pid_t pid;
    int status;
    pid = waitpid(-1, &status, WNOHANG);  //销毁子进程
    printf("removed proc id: %d \n", pid);
}

回声客户端:

/*********************************************************************************
 *      Copyright:  (C) 2018 weirenqiu
 *                  All rights reserved.
 *
 *       Filename:  mul_pro_client.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(05/16/2018)
 *         Author:  weirenqiu <>
 *      ChangeLog:  1, Release initial version on "05/16/2018 02:09:29 PM"
 *                 
 ********************************************************************************/

/********************************************************************************
 *  Description:The parent process receives the data, and the subprocess sends the data.
 *   Input Args:
 *  Output Args:
 * Return Value:
 ********************************************************************************/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define BUF_SIZE 1024
void read_data(int sockfd,char *buf);
void write_data(int sockfd,char *buf);
int main (int argc, char **argv)
{   
    int            sockfd = -1;
    pid_t           pid;
    char buf[BUF_SIZE];
    struct sockaddr_in serv_addr;

    if(argc !=3)
    {
        printf("Usage:%s   \n",argv[0]);
        exit(1);

    }
    if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
        printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
        exit(1);
    }
        memset(&serv_addr, 0, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(atoi(argv[2]));
        if( inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0){
            printf("inet_pton error for %s\n",argv[1]);
            exit(1);
        }
        if( connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0){
            printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
            exit(1);
        }


    /*if( (fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
    {   printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(atoi(argv[2]));
    if( inet_pton(AF_INET, argv[1], &serva_ddr.sin_addr) <= 0)
    {
        printf("inet_pton error for %s\n",argv[1]);
        exit(0);
    }

    if (connect(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) == -1)
    {
        printf("connect socket error: %s(errno: %d)\n",strerror(errno),errno);
        exit(0);

    }*/

    /*Customer service I/O segmentation, the parent process is responsible for receiving data, and the child process is responsible for sending data.
     * This separation can improve the performance of the programs that frequently exchange data, without having to do the same as before,
     * You can only send the next one after you have received the last piece of data.*/

    pid =fork();
    if(pid == 0){
        printf("one\n");
        write_data(sockfd,buf);
    }
    else

        read_data(sockfd,buf);
    
    close(sockfd);
    

    return 0;


} /* ----- End of main() ----- */

void read_data(int sockfd,char *buf)
{
    while(1)
    {
        int str_len = read(sockfd,buf,BUF_SIZE);
        if(str_len == 0)
            return;
        buf[str_len] = 0;
        printf("message  from server:%s",buf);

    }
}

void write_data(int sockfd ,char *buf)
{
    while(1)
    {
        fgets(buf,BUF_SIZE,stdin);

        if (!strcmp(buf, "q\n") || !strcmp(buf, "Q\n"))
        {
            shutdown(sockfd,SHUT_WR);
        }
        write(sockfd,buf,strlen(buf));
    }
}

你可能感兴趣的:(linux)