linux下多线程服务器编程

前言:整个程序的架构就是一开始创建一个线程,在这个线程里面做下面几个操作:
1、调用socket,创建监听客户端的socket
2、设置socket属性,端口可以重用
3、调用bind,绑定地址和端口
4、调用listen,开始监听
5、调用while(1)循环
6、 每新连接一个就创建一个线程用来做连接处理

while(1)
{
	//调用accept,返回与服务器连接的客户端描述符
	if ((connectfd = accept(listenfd,(struct sockaddr *)&client,(socklen_t *)&sin_size))==-1) 	 {                    
 	sys_err("accept() error\n");
}

//多线程初始化

void server_init()
{
    pthread_t	thdrec;
    pthread_attr_t attr;
	if(pthread_attr_init(&attr))
    {
		printf("pthread init error\n");
    }
    //threadfunc defined in netmsg.h
    if(pthread_create(&thdrec,&attr,threadfunc,0))
    {
		printf("creat pthread error\n");
    }  
}

//在多线程中开启监听

void *threadfunc(void * arg)
{
	printf("threadfunc\n");
	uint16_t port  = 9000;
	tcp_server(port);
}

//绑定端口后开始监听端口

void tcp_server(uint16_t port)//this port unused
{
	int listenfd;				   //socket描述符
    struct sockaddr_in server;     //服务器地址信息结构体
   
	
    //调用socket,创建监听客户端的socket
    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 
        sys_err("Creating socket failed.");
    }
	
    //设置socket属性,端口可以重用
    int opt = SO_REUSEADDR;        
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));    
	
    //初始化服务器地址结构体
    bzero(&server,sizeof(server));
    server.sin_family=AF_INET;
    server.sin_port=htons(PORT);
    server.sin_addr.s_addr = htonl (INADDR_ANY);
	
    //调用bind,绑定地址和端口
    if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) {   
        sys_err("Bind error.");
    }   
	
    //调用listen,开始监听
    if(listen(listenfd,BACKLOG) == -1){      
        sys_err("listen() error\n");
    }
    
	//处理客户端链接的接收工作
    accept_conn(listenfd);

	//关闭监听socket
    close(listenfd);        
}

//处理客户端链接的接收工作*

void accept_conn(int listenfd)
{
	 int  connectfd;       		   //socket描述符
     pthread_t  connectthread;	   //线程体变量
     ARG *arg;                      //客户端结构体变量
	 struct sockaddr_in client;     //客户端地址信息结构体
     int sin_size = sizeof(struct sockaddr_in);
	 pthread_attr_t attr;
	 while(1) {
        //调用accept,返回与服务器连接的客户端描述符
        if ((connectfd = accept(listenfd,(struct sockaddr *)&client,(socklen_t *)&sin_size))==-1) {                    
            sys_err("accept() error\n");
        }
        
        arg = new  ARG;
        arg->connfd = connectfd;
		sendfd = connectfd;

        memcpy(&arg->client, &client, sizeof(client));
        
		//创建线程,以客户端连接为参数,start_routine为线程执行函数
	    pthread_attr_init (&attr);
	    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
        if (pthread_create(&connectthread, &attr, start_routine, (void*)arg)) {        
            sys_err("Pthread_create() error");
        }
	    pthread_attr_destroy (&attr);
    }
}
void process_cli(int connectfd, struct sockaddr_in client);    //客户端请求处理函数
void* start_routine(void* arg);        //线程处理函数
typedef struct  _ARG  {
    int connfd;
    struct sockaddr_in client; 
}ARG;                    		  //客户端结构体

void* start_routine(void* arg)
{
    ARG *info = (ARG *)arg;
    process_cli(info->connfd, info->client);
	//删除对应的堆内存
	delete info;
    pthread_exit(NULL);
} 

void process_cli(int connectfd, sockaddr_in client)
{
	hiBsp_Size size;
	hiBsp_Rect rect;
	int x,y;
    int num;
    char recvbuf[MAXDATASIZE], sendbuf[MAXDATASIZE], cli_name[MAXDATASIZE];
    wSip_Msg2 dev_msg;
    printf("You got a connection from %s.  \n",inet_ntoa(client.sin_addr) );
	//MSG_WAITALL 
    while ((num = recv(connectfd, recvbuf, MAXDATASIZE,0)) > 0)
    {
 		recvbuf[num] = '\0';
        printf("Received size( %d ) message: %x\n",num, recvbuf);
		for(int i=0;i<num-1;i++)
		{
			//printf(" %x",recvbuf[i]);
		}
	}
	close(connectfd); 
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值