Linux 环境实现简单的TCP多并发服务器

 在网络通信中,服务器通常需要处理多个客户端。由于客户端的请求会同时到来,服务器端可能会采用不同的方法来处理。总体来说,服务器端可采用两种模式来实现:循环服务器模型和并发服务器模型。

循环服务器模型是指服务器端依次处理每个客户端,直到当前客户端的所有请求处理完毕,在处理下一个客户端。这类模型的优点是简单,缺点显而易见,这样会造成其他客户端等待时间过长。

为了提高服务器的并发处理能力,引入了并发服务器模型。其基本思想是在服务器端采用多任务机制(多线程或者多进程),分别为每一个客户端创建一个任务来处理,极大的提高了服务器的并发处理能力。并发服务器模型也是本片博客要实现的。

下面是搜索到的一张TCP服务器与客户端建立连接与进行通信的过程,描述的非常形象。

 实例代码

/*
 server.c
*/

#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
 
int main(int argc, const char * argv[])
{
    pid_t pid;
    int ser_socket;
    struct sockaddr_in servaddr,cliaddr;
    int addr_len = sizeof(cliaddr);
    int client;
    char buffer[4000],renew[4000];
    int datanum;
	
	if(argc < 3)
	{
		printf("Usage:%s <IP> <port>\n", argv[0]);	//提示输入
		exit(-1);
	}
    
    if ((ser_socket = socket(AF_INET,SOCK_STREAM,0))<0)
    {
        perror("socket");
        return -1;
    }
    
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(atoi(argv[2]));
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);
    
    if(bind(ser_socket,(struct sockaddr *)&servaddr,sizeof(servaddr))<0)
    {
        perror("bind");
        return -1;
    }
    
    if(listen(ser_socket, 10)<0)
    {
        perror("listen");
        return -1;
    }
    //等待请求
    while (1) {
        printf("Listening on port :%d\n",atoi(argv[2]));
        client = accept(ser_socket, (struct sockaddr*)&cliaddr, (socklen_t *)&addr_len);
        if(client<0)
        {
            perror("accept");
            continue;
        }
        printf("\n recv client data:\n");
        printf("IP is %s\n",inet_ntoa(cliaddr.sin_addr));
        printf("port is %d\n",htons(cliaddr.sin_port));
        //进行对话,创建线程
        if((pid = fork())==0)
        {
         close(ser_socket);
        while(1)
        {
            datanum = recv(client, buffer, 4000, 0);// 收数据
            if(datanum< 0)
            {
                perror("recv");
                continue;
            }
            buffer[datanum] = '\0';
            printf("%d:say %s\n", htons(cliaddr.sin_port), buffer);
            printf("you want to say:");
            scanf("%s",renew);
            send(client, renew, strlen(renew), 0);
            if(strcmp(renew, "quit") == 0)
            {
                exit(0);//销毁此线程
                break;
            }
        }
        }
    }
    
    return 0;
}
/*
 client2.c
*/

#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
 
 
int main(int argc, const char * argv[]) 
{
    int client_socket;
    struct sockaddr_in servaddr;
    char sendbuf[400];
    char recbuf[400];
    int sennum,recnum;
	
	if(argc < 3)
	{
		printf("Usage:%s <IP> <port>\n", argv[0]);	//提示输入
		exit(-1);
	}
	
    if((client_socket= socket(AF_INET, SOCK_STREAM, 0))<0)
    {
        perror("socket");
        return -1;
    }
    
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(atoi(argv[2]));
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);
    
    if(connect(client_socket, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
    {
        perror("connect");
        return 1;
    }
    
    printf("connect with destination host...\n");
    
    while(1)
    {
        printf("Input your world:>");
        scanf("%s", sendbuf);
        printf("\n");
        
        send(client_socket, sendbuf, strlen(sendbuf), 0);
        
        recnum = recv(client_socket, recbuf, 4000, 0);
        recbuf[recnum] = '\0';
        printf("recv is: %s\n", recbuf);
        if(strcmp(recbuf, "quit") == 0)
            break;
    }
    close(client_socket);
    
    return 0;
}
/*
 client2.c
*/

#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
 
 
int main(int argc, const char * argv[]) {
    int client_socket;
    struct sockaddr_in servaddr;
    char sendbuf[400];
    char recbuf[400];
    int sennum,recnum;
	
	if(argc < 3)
	{
		printf("Usage:%s <IP> <port>\n", argv[0]);	//提示输入
		exit(-1);
	}
	
    if((client_socket= socket(AF_INET, SOCK_STREAM, 0))<0)
    {
        perror("socket");
        return -1;
    }
    
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(atoi(argv[2]));
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);
    
    if(connect(client_socket, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
    {
        perror("connect");
        return 1;
    }
    
    printf("connect with destination host...\n");
    
    while(1)
    {
        printf("Input your world:>");
        scanf("%s", sendbuf);
        printf("\n");
        
        send(client_socket, sendbuf, strlen(sendbuf), 0);
        
        recnum = recv(client_socket, recbuf, 4000, 0);
        recbuf[recnum] = '\0';
        printf("recv is: %s\n", recbuf);
        if(strcmp(recbuf, "quit") == 0)
            break;
    }
    close(client_socket);
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/David_361/article/details/86538961