pthread_create()简要介绍
pthread_create()函数是创建线程(实际上就是确定调用该线程函数的入口点),在线程创建以后,就开始运行相关的线程函数。 pthread_create的返回值表示成功,返回0;表示出错,返回表示-1。
pthread_detach()简要介绍
int pthread_detach(pthread_t thread); 成功:0;失败:错误号
作用:从状态上实现线程分离
线程分离状态:指定该状态,线程主动与主控线程断开关系。线程结束后(不会产生僵尸线程),其退出状态不由其他线程获取,而直接自己自动释放(自己清理掉PCB的残留资源)。网络、多线程服务器常用。
代码分析
pthread非linux系统的默认库, 需手动链接-线程库 -lpthread
gcc server.c wrap.c -o server -lpthread
“undefined reference to”的意思是,该函数未定义。
如果提示未定义的函数是某个库的函数。检查库时候已经安装,并在编译命令中采用-l和-L参数导入库。
如果提示未定义的函数是程序中的函数。检查是否在头文件中声明,是否在编译中有对应的obj文件。
如果提示未定义的函数是程序中的函数,还有一种很隐蔽的可能:检查改函数的代码的上下文是否有#ifdef或者#ifndef等预编译信息,这也很有可能导致相关代码没有被编译而出现“undefined reference to”提示。
代码
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include "wrap.h"
struct client_info{
struct sockaddr_in cliaddr;
int connfd;
};
//线程执行的工作
void *do_work(void *arg)
{
struct client_info *ts = (struct client_info*)arg;
while(1){
char buf[1024];
int n = Read(ts->connfd,buf,1024);
//如果接收到的数据长度为0 那么就是已经结束了
if(n==0) {
printf("the client %d closed....\n", ts->connfd);
break;
}
//打印客户端信息
char str[INET_ADDRSTRLEN];
printf("received from %s at port %d\n",
inet_ntop(AF_INET, &(*ts).cliaddr.sin_addr, str, sizeof(str)),
ntohs((*ts).cliaddr.sin_port));
//转换大小写
int i;
for (i = 0; i < n; i++)
buf[i] = toupper(buf[i]); //小写-->大写
//写数据
Write(STDOUT_FILENO, buf, n); //写出至屏幕
Write(ts->connfd, buf, n); //回写给客户端
}
Close(ts->connfd);
return (void *)0;
}
int main(void)
{
//创建一个监听socket
int listenfd= Socket(AF_INET,SOCK_STREAM,0);
//建立并绑定监听地址
struct sockaddr_in servaddr;
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(7000);
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
Bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
//设置监听个数
Listen(listenfd,20);
printf("accepting client connect....\n");
//创建一个用于保存客户端数据的结构体
struct client_info cinfo[256];
int i=0;
pthread_t tid;//线程
while(1){
//创建一个用于接收客户地址的sockaddr_in
struct sockaddr_in cliddr;
socklen_t cliaddr_len = sizeof(cliddr);
//返回连接的文件描述符
int connfd = Accept(listenfd,(struct sockaddr *)&cliddr,&cliaddr_len);
//将信息都保存到结构体数组中
cinfo[i].cliaddr=cliddr;
cinfo[i].connfd=connfd;
pthread_create(&tid, NULL, do_work, (void*)&cinfo[i]);
pthread_detach(tid);
i++;
}
return 0;
}