服务器端编程实例(四 多线程并发)

本文介绍了一个使用多线程并发处理客户端请求的服务器端编程实例。通过创建新的线程来处理每个连接请求,主线程继续监听。文章详细讲解了如何使用pthread_create创建线程,并传递参数到线程函数中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
程序说明   多线程并发,在接收到请求时,将每个请求创建个线程来执行,原线程 ( 即主线程 ) 继续 listen.
在创建多线程时的主要问题是传入线程参数。
 
NAME
       pthread_create - create a new thread
SYNOPSIS
       #include <pthread.h>
       int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg);
/***************************************************************************
*     author: denny wqf363@hotmail.com 2006  
*     desc:  多线程并发
*     座友铭:凡是程序当前不需要的,都是垃圾,80%的时间做20%的事情。(程序的效率)
*                                                                          *
***************************************************************************/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include      <malloc.h>
#include <stdlib.h>
 
#define BACKLOG 5
#define MAXDATASIZE 1000
#define PORT 1234
 
void process_cli(int,sockaddr_in);
void* pthread_receive(void* arg);
 
*/
//for mulThread
//多线程传递参数为结构体类型
struct ARG
{
int connectfd;
sockaddr_in client;
};
 
int main(int argc,char *argv[])       //需要一个参数 端口号
{
    int    listenfd,                        //监听套接字sock
       connectfd;               //accept 收到的 新套接字
    struct sockaddr_in servAddr,       //服务器地址
                cliAddr;   //客户端地址
    socklen_t adrlen;                   //sockaddr地址长度
    int           servPort;               //服务器监听端口号
    pid_t             pid;                /*进程ID,多进程程序使用*/
    /*struct packagehead *packhead;*/      //数据包头,下面是多线程所要所用到的变量
    ARG      *arg;
    int    rc;
    pthread_t id;
 
    //获得服务器监听的端口号
    if(argc!=2)
    {
        printf("Usage:%s portnumber/a/n",argv[0]);
        return 1;
    }
    if((servPort=atoi(argv[1]))<0)
    {
        printf("Usage:%s portnumber/a/n",argv[0]);
        return 1;
    }
 
    /* 服务器端开始建立socket描述符 */
    if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1)
    {
        fprintf(stderr,"Socket error:%s/n/a",strerror(errno));
        return 1;
    }
 
    /*设置套接字地址结构体servAddr中的参数,绑定服务器端口号*/
    bzero(&servAddr,sizeof(servAddr));     //将servAddr结构体重置
    servAddr.sin_family=AF_INET;
    servAddr.sin_addr.s_addr=htonl(INADDR_ANY);
    servAddr.sin_port=htons(servPort);
 
    if(bind(listenfd,(struct sockaddr *)&servAddr,sizeof(servAddr))<0)
    {
        printf("Bind error:%s/n/a",strerror(errno));
        exit(2);
    }
    /* 监听sockfd描述符 */
    if(listen(listenfd,BACKLOG)==-1)
    {
        printf("Listen error:%s/n/a",strerror(errno));
        exit(3);
    }
 
    while(1)
    {
        printf("%s:waiting for data on port TCP %u/n",argv[0],servPort);
       
         adrlen=sizeof(struct sockaddr_in);
        connectfd=accept(listenfd,(struct sockaddr *)&cliAddr,&adrlen);
        if(connectfd<0)
        {
            /*printf("Accept error:%s/n/a",strerror(errno));
            close(*new_sd);
            free(new_sd);*/
            perror("accetp() error/n");
            exit(4);
        }
 
        //采用多线程并发3,新线程传递参数变量用指针
        arg=new ARG;
        arg->connectfd=connectfd;
        memcpy((void *)&arg->client,&cliAddr,sizeof(cliAddr));
       
        rc=pthread_create(&id,NULL,pthread_receive,(void *)arg);
        if(rc!=0)
        {
            printf("Create pthread errer:%s/n/a",strerror(errno));
            /*close(*new_sd);
            free(new_sd);*/
            exit(5);
        }
       
    }
    close(listenfd);
}
 
void process_cli(int connectfd, sockaddr_in client)
{
       //....
    close(connectfd);
}
 
void* pthread_receive(void* arg)
{
ARG *info;
info=(ARG *)arg;
process_cli(info->connectfd,info->client);
 
delete arg;
pthread_exit(NULL);
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值