2-25 并发服务器程序设计

(本节笔记的实验代码,在这里


1.  并发服务器程序设计原因
        采用轮询方式接收来自客户端的连接请求,服务器端只能按顺序处理数个客户端的连接请求,也就是只能处理完A客户端的连接和数据收发后,才能按顺序继续处理B和C的客户端的请求。

2.  改善方法
        服务器端采用多进程或多线程的方式,来同时并发处理来自多个客户端的连接请求。(若是TCP采用多进程方式)处理方法是,在父进程建立连接,而子进程负责进行数据的收发以及关闭客户端的连接的工作。

3.  综合实例

/*  touch tcp_client_pthread.c  */

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


#define PORTNUM 3333


int main(int argc, char **argv)
{
    if(argc != 3)
    {
        printf("Usage: %s serverIP serverPort", argv[0]);
        exit(1);
    }
    int sockfd;
    char server_addr_a[4];
    long addr_len;
    char buffer[128];
    struct sockaddr_in server_addr;


    /* 1.创建socket */
    if(-1 == (sockfd = socket(AF_INET, SOCK_STREAM, 0)))
    {
        printf("Create socket fail!\n");
        exit(1);
    }
    /* 2.建立连接 */
    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(atoi(argv[2]));
    server_addr.sin_addr.s_addr = inet_addr(argv[1]);
    if(-1 == (connect(sockfd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr))))
    {
        printf("Create connect fail!\n");
        exit(1);
    }
    else
        printf("Create connect with %s successful!\n", argv[1]);
    while(1)
    {
        /* 3.发送数据 */
        printf("Please input something, input \"quit\" for close the client, \"end\" for exit for server:\n");
        fgets(buffer, 128, stdin);
        if(-1 == send(sockfd, buffer, strlen(buffer), 0))
        {
            printf("Send message fail!\n");
            exit(1);
        }
        else
            printf("The message had been sended!\n");
        
        if(0 == strncmp(buffer, "quit", 4))
        {
            printf("Client will be close!\n");
            break;
        }
        if(0 == strncmp(buffer, "end", 3))
        {
            printf("Server and Client will be close!\n");
            break;
        }
    }
    /* 4.结束app连接 */
    close(sockfd);


    return 0;
}


/*  touch tcp_server_pthread.c  */

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


#define PORTNUM 3333
#define BUFF_SZ 128


struct arg
{
    int con_fd;
    struct sockaddr_in con_addr;
};


void * thread_fun(void *arg)
{
    struct arg arg_thread;
    arg_thread.con_fd = ((struct arg *)arg)->con_fd;
    arg_thread.con_addr = ((struct arg *)arg)->con_addr;


    /* 5.接收数据 */
    char buff[BUFF_SZ];
    bzero(buff, sizeof(buff));
    int recv_sz = 0;
    while(1)
    {
         recv_sz = recv(arg_thread.con_fd, buff, BUFF_SZ, 0);
        if(0 != recv_sz)
        {
            buff[recv_sz] = '\0';
            printf("Server has received the message from : %s\n", inet_ntoa(arg_thread.con_addr.sin_addr.s_addr));
            printf("The message is : %s\n", buff);        
            recv_sz = 0;
            if(0 == strncmp(buff, "quit", 4))
            {
                printf("Client with %s will be close!\n", inet_ntoa(arg_thread.con_addr.sin_addr.s_addr));
                /* 6.结束app连接 */
                close(arg_thread.con_fd);
                pthread_exit(NULL);
            }
            if(0 == strncmp(buff, "end", 3))
            {
                printf("Server and Client will be close!\n");
                /* 6.结束app连接 */
                close(arg_thread.con_fd);
                exit(0);   
            }
        }
    }
       
}




int main()
{
    int sockfd;
    int acc_fd;
    pthread_t thread_id;
    long addr_len;
//    char client_addr_a[10];
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;


    /* 1.创建socket */
    if(-1 == (sockfd = socket(AF_INET, SOCK_STREAM, 0)))
    {
        printf("Create socket fail!\n");
        exit(1);
    }
    /* 2.绑定地址 */
    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORTNUM);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    bind(sockfd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr));
    /* 3.监听连接 */
    listen(sockfd, 5);
    while(1)
    {
        /* 4.等待连接 */
        addr_len = sizeof(struct sockaddr);
        if(-1 == (acc_fd = accept(sockfd,(struct sockaddr*)(&client_addr), (socklen_t *)(&addr_len))))
        {
            printf("Create server connect fail!\n");
            exit(1);
        }
        printf("The server has connect with %s\n", inet_ntoa(client_addr.sin_addr.s_addr));


        struct arg arg_thread;
        arg_thread.con_fd = acc_fd;
        memcpy(&(arg_thread.con_addr), &client_addr, sizeof(struct sockaddr_in));
        if(-1 == pthread_create(&thread_id, NULL, thread_fun, (void *)&arg_thread))
        {
            printf("Create pthread fail!\n");
            exit(1);
        }


    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值