TCP并发服务器多线程

1.创建线程‐‐pthread_create
int pthread_create( pthread_t *thread, // 线程 ID = 无符号长整型
const pthread_attr_t *attr, // 线程属性, NULL
void *(*start_routine)(void *), // 线程处理函数
void *arg); // 线程处理函数
参数:
pthread: 传出参数,线程创建成功之后,会被设置一个合适的值
attr: 默认传 NULL
start_routine: 子线程的处理函数
arg: 回调函数的参数
返回值:
成功 :0
错误 : 错误号 //perror 不能使用该函数打印错误信息
主线程先退出,子线程会被强制结束
验证线程直接共享全局变量
client

objectivec 复制代码
#include<stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include<stdlib.h>
#include <strings.h>
#include<unistd.h>

#include <string.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//./client 192.168.182.144 5001




#define SERV_PORT 5001
#define SERV_IP_ADDR "192.168.157.34"
#define BUFSIZE 1024
#define QUIT_STR "QUIT"


int main(int argc,char **argv)
{
        int fd = -1;
        if(argc!=3)
        {
        exit(1);
        }
        int port = -1;
        port = atoi(argv[2]);
        fd = socket(AF_INET,SOCK_STREAM,0);
        if(fd<0)
        {

                perror("socket");
                exit(1);
        }

        struct sockaddr_in sin;
        bzero(&sin,sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_port = htons(port);
        sin.sin_addr.s_addr = inet_addr(argv[1]);

        if(connect(fd,(struct sockaddr*)&sin,sizeof(sin))<0)
        {
                perror("connect");
                exit(1);
        }
        char buf[BUFSIZE];
        while(1)
        {
                bzero(buf,BUFSIZE);
                if(fgets(buf,BUFSIZE-1,stdin)==NULL)
                {
                        continue;
                }
               write(fd,buf,strlen(buf));
                if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
                {

                        break;
                }


        }
        return 0;


}

service

objectivec 复制代码
#include<stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include<stdlib.h>
#include <strings.h>
#include<unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include<pthread.h>
#define SERV_PORT 5001
#define SERV_IP_ADDR "192.168.157.34"
#define BACKLOG 5
#define BUFSIZE 1024
#define QUIT_STR "QUIT"
void* client_data_handle(void* arg);
int main(int argc,char *argv[])
{
        //socket
        int fd = -1;
        pthread_t tid;//定义pthread_t 类型的参数,成功时指向的内存单元为新创建线程的线程ID
        fd = socket(AF_INET,SOCK_STREAM,0);//三个参数:ipv4网络协议,流式套接字,唯一对应TCP,协议一般填写0。成功返回文件描述符fd
        if(fd < 0)
        {
                perror("socket");
                exit(1);
        }
        /*
           struct sockaddr_in {
           sa_family_t    sin_family;  address family: AF_INET 
           in_port_t      sin_port;    port in network byte order 
           struct in_addr sin_addr;    internet address 
           };

           Internet address. 
           struct in_addr {
           uint32_t       s_addr;      address in network byte order 
           };  */

        struct sockaddr_in sin;

        bzero(&sin,sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_port = htons(SERV_PORT);
        sin.sin_addr.s_addr = INADDR_ANY;
        //bing
        if(bind(fd,(struct sockaddr *)&sin,sizeof(sin))<0)//绑定函数,与sockaddr_in结构体联系
        {
                perror("bind");
                exit(1);
        }

        //listen

        if(listen(fd,BACKLOG)<0)//监听函数,表示系统允许2*backlog+1个客户端同时进行三次握手
        {
                perror("listen");
                exit(1);
        }
       int newfd = -1;
        char ipv4_addr[16];
        struct sockaddr_in clin;

        socklen_t sockaddr_len = sizeof(clin);
        while(1)
        {
                newfd = accept(fd,(struct sockaddr *)&clin,&sockaddr_len);//持续接收,参数:之前的文件描述符,新定义的结构体,socklen_t 类型的结构体长度。accept函数用法同bind,但结构体不同,结构体内容一样,第三个参数不同,bind 为结构体长度,accept需要为socklen_t 类型的变量,变量值为结构体的长度。返回为另一个文件描述符newfd。即服务器接收到用户端的信息后会返回一个新的文件描述符。
                if(newfd<0)
                {
                        perror("accept");
                        exit(1);
                }
                if(!inet_ntop(AF_INET,(void *)&clin.sin_addr,ipv4_addr,sizeof(clin)))
                {
                        perror("inet_ntop");
                        exit(1);
                }
                printf("client :(%s,%d) is connect!\n",ipv4_addr,ntohs(clin.sin_port));

                pthread_create(&tid,NULL,client_data_handle,(void *)&newfd);//创建线程,线程为tid,成功时tid指向的内存单元为新线程的id,线程描述为NULL,新创建线程从此函数开始运行,子线程函数的参数,有参数时输入参数的地址,当多余一个参数时用结构体传入

        }
        close(fd);
        //read



}

void* client_data_handle(void* arg) //子线程处理函数
{
        int newfd = *(int *)arg; //将传入的参数的值给newfd
        char buf[BUFSIZE];
        int ret = -1;
        printf("handle thread :newfd= %d\n",newfd);
        while(1)
        {

                do{
                        bzero(buf,BUFSIZE);
                        ret = read(newfd,buf,BUFSIZE-1);

                }while(ret<1);
                if(ret<0)
                {
                        perror("read");
                        exit(1);
                }
                if(!ret)
                {
                        break;
                }
                printf("receive data :%s \n",buf);

                if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
                {
                        printf("Client is exiting!\n");
                        break;
                }
        }
        close(newfd);
        return NULL;

}

结果

相关推荐
努力进修3 分钟前
“探索Java List的无限可能:从基础到高级应用“
java·开发语言·list
Komorebi.py1 小时前
【Linux】-学习笔记05
linux·笔记·学习
Mr_Xuhhh1 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
Ajiang28247353042 小时前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
中云DDoS CC防护蔡蔡2 小时前
微信小程序被攻击怎么选择高防产品
服务器·网络安全·微信小程序·小程序·ddos
幽兰的天空2 小时前
Python 中的模式匹配:深入了解 match 语句
开发语言·python
HPC_fac130520678163 小时前
以科学计算为切入点:剖析英伟达服务器过热难题
服务器·人工智能·深度学习·机器学习·计算机视觉·数据挖掘·gpu算力
yaoxin5211234 小时前
第二十七章 TCP 客户端 服务器通信 - 连接管理
服务器·网络·tcp/ip
内核程序员kevin4 小时前
TCP Listen 队列详解与优化指南
linux·网络·tcp/ip
Theodore_10225 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee