/*************************************************************************
> File Name: multi_pthread-server.c
> Author: xuchen_allen
> Mail: [email protected]
> Created Time: 2019年02月10日 星期日 21时53分43秒
************************************************************************/
#include<stdio.h>
#include<string.h>
#include<arpa/inet.h>
#include<pthread.h>
#include<ctype.h>
#include<unistd.h>
#include<fcntl.h>
#define SER_PORT 8080
//封装一个结构体,将地址与cfd绑定,可以作为函数参数传给线程操作函数;
struct s_info
{
struct sockaddr_in cliaddr;
int connfd;
};
void *do_work(void *arg) //线程操作函数,规定线程的动作;
{
//套接字,协议设定,绑定,监听,连接都在主线程中完成:
int n,i;
struct s_info *ts = (struct s_info*)arg; //pthread_create传入的参数,存放线程的一些信息;
char buf[1024];
char str[100];
while(1){
n = read(ts->connfd,buf,sizeof(buf));
if(n==0){
printf("disconnect\n");
break;
}
printf("客户端IP:%s \t,端口:%d \n",inet_ntop(AF_INET,&(*ts).cliaddr.sin_addr,str,sizeof(str)),ntohs((*ts).cliaddr.sin_port));//打印客户端的信息;
write(STDOUT_FILENO,buf,n);
}
close(ts->connfd);
return NULL;
}
int main(void)
{
//定义套接字:
struct sockaddr_in servaddr,cliaddr;
socklen_t cliaddr_len;
int listenfd,connfd;
pthread_t tid;
struct s_info ts[256]; //用来存放各个子线程的信息,与上面定义的结构体封装相适应;
int i=0;
listenfd = socket(AF_INET,SOCK_STREAM,0);
//指定协议:
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SER_PORT);
bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)); //绑定
listen(listenfd,128); //监听:
printf("Waitting connection...\n");
while(1){
cliaddr_len = sizeof(cliaddr);
connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&cliaddr_len); //阻塞监听客户端请求:
ts[i].cliaddr = cliaddr;
ts[i].connfd = connfd;
//用数组元素储存线程的信息;
pthread_create(&tid,NULL,do_work,(void*)&ts[i]);
pthread_detach(tid); //分离线程,防止僵尸线程的产生;
i++;
if(i==256)
break;
}
return 0;
注意线程创建函数的传入参数的封装;