Linux C/C++ 开发(学习笔记十一 ):TCP服务器(并发网络网络编程 一请求一线程)

简介: Linux C/C++ 开发(学习笔记十一 ):TCP服务器(并发网络网络编程 一请求一线程)

一、TCP服务器(一请求一线程) 的原理

通过sockfd绑定(bind)和监听(listen),每过来一个客户端就接受(accept),并创建一个clientfd,每个clientfd,占据一个线程。

每个线程执行 接受(recv)并printf的任务。

具体的监听过程

二、完整代码

#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
#include<unistd.h>
#define BUFFER_LENGTH 1024
void* client_routine(void* arg){
    int clientfd=*(int*)arg;
    while(1){
        char buffer[BUFFER_LENGTH]={0};
        int len=recv(clientfd,buffer,BUFFER_LENGTH,0);//阻塞就会挂起
        if(len<0){//阻塞io不存在len<0因为它会挂起在recv时刻,一旦发生,就说明出错了
            close(clientfd);
            break;
        }else if(len==0){//disconnect (读取数据为0就说明客户端断开连接了)
            close(clientfd);
            break;
        }else{
            printf("Recv:%s,%d bytes\n",buffer,len);
        }
    }
}
int main(int argc,char** argv){
    if(argc<2){
        printf("Param Error\n");
        return -1;
    }
    int port=atoi(argv[1]);
    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    sockaddr_in addr;
    memset(&addr,0,sizeof(sockaddr_in));
    addr.sin_family=AF_INET;
    addr.sin_port=htons(port);
    addr.sin_addr.s_addr=INADDR_ANY;//0.0.0.0 泛指本机的意思
    if(bind(sockfd,(sockaddr*)&addr,sizeof(sockaddr_in))<0){//绑定
        perror("bind");
        return 2;
    }
    if(listen(sockfd,5)<0){//监听(最多可以排队5个)
        perror("listen");
        return 3;
    }
    //一请求 一线程
    while(1){
        sockaddr_in client_addr;
        memset(&client_addr,0,sizeof(sockaddr_in));
        socklen_t client_len = sizeof(client_addr);
        int clientfd = accept(sockfd,(sockaddr*)&client_addr,&client_len);//接受一个客户,并将它的ip存到client_addr中,并形成了一个客户端fd
        pthread_t thread_id;
        pthread_create(&thread_id,NULL,client_routine,&clientfd);//为每个clientfd分配一个线程
    }
    return 0;
}

编译指令

g++ tcp_sever.cpp -o tcp_sever -lpthread

三、测试

执行,设置服务器端口为8888

./tcp_server 8888

打开NetAssist.exe

选择TCP Client,远程主机是自己的服务器的ip:端口号

点击连接

然后在下方可以发送数据了,点击发送

在服务器端可以接受到数据

四、补充

多个客户端,如何区分哪个客户端发送的?

sockfd是解决不了的

通过定义应用协议来解决,比如说在发送的同时也发送 用户id

一请求一线程 的缺点:

随着客户端越来越多 (比如100w)

不合适用一请求一线程的方式。

posix thread 8M。 1G内存 —》128个。比较有限。

现在已经弃用了,而选用epoll的方式


相关文章
|
1天前
|
网络协议 Linux Shell
【linux网络(一)】初识网络, 理解四层网络模型
【linux网络(一)】初识网络, 理解四层网络模型
|
1天前
|
安全 Ubuntu Linux
Linux 网络操作命令Telnet
Linux 网络操作命令Telnet
12 0
Linux 网络操作命令Telnet
|
2天前
|
Ubuntu Linux
Linux(22) Linux设置网络优先级顺序
Linux(22) Linux设置网络优先级顺序
3 0
|
3天前
|
Ubuntu 网络协议 Linux
Linux(20) Ubuntu 20.04 网络接口自动切换路由配置
Linux(20) Ubuntu 20.04 网络接口自动切换路由配置
26 0
|
3天前
|
存储 编译器 C语言
c++的学习之路:5、类和对象(1)
c++的学习之路:5、类和对象(1)
18 0
|
2天前
|
C++
c++的学习之路:7、类和对象(3)
c++的学习之路:7、类和对象(3)
19 0
|
1天前
|
设计模式 Java C++
【C++高阶(八)】单例模式&特殊类的设计
【C++高阶(八)】单例模式&特殊类的设计
|
1天前
|
编译器 C++
【C++基础(八)】类和对象(下)--初始化列表,友元,匿名对象
【C++基础(八)】类和对象(下)--初始化列表,友元,匿名对象
|
5天前
|
存储 安全 C语言
【C++】string类
【C++】string类
|
存储 编译器 Linux
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”