1、intpthread_create(pthread_t *tid,const pthread_attr_t*attr,void*(*func)(void*),void*arg),我想大家可以看得出这就是线程的创建函数。这个函数包含在头文件#include中,共有四个指针形参,所以线程的创建函数又叫做四针函数,其中第一个参数表示线程ID,第二个是线程属性,很多情况下给0就可以(好像又听说linux下只支持0,但不确定),第三个参数是一个函数指针,用于执行自己的线程函数,传入的就是自定义线程函数的函数指针。第四个参数的作用是我们可以传入一个我们需要的参数给线程函数,后面的程序中大家就会明白。
2、pthread_join(pthread_ttid,void**status),这个函数的作用是让一个线程等待另一个线程的结束。当我们不希望得到线程函数的返回值时,第二个参数给0.例如我们在线程A中写了pthread_join(B,0),就表示A线程要等到b线程的结束。类似于进程中的waitpid()函数。函数的第二个参数用于带出线程函数的返回值,我认为大家可以理解一下为什么是二级指针。当然,第一个参数表示线程ID。
3、pthread_self(),没有形参,函数的作用是取得自己的线程ID。
4、pthread_detach(pthread_ttid),函数的作用是讲一个线程设置为分离线程。分离线程是什么意思呢?由于线程在回收资源上是不确定的,就是说没有固定的说法说他什么时候回收。当一个线程是分离线程的时候,只要他结束,所有的资源都会释放。还有一种线程是pthread_join()过得线程,也会在执行这个函数之后释放所 有资源,所以我们最好是把线程设置成这两种类型。形参表示线程ID。
5、pthread_exit(void*status),用于退出线程。
值得注意的是,这一块的函数的返回值基本都是返回错误码,并不是以前的错误返回-1什么的,错误码通过strerror()函数可以解析出错误的信息。
线程这块还有一些知识,比如线程同步,线程尺这些,由于没用到,就不细说了,下面我们先搭建聊天室的服务器端。
/*基于TCP协议的多线程聊天室服务器端*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
char *IP = "192.168.1.100"; //服务器IP号
short PORT = 5555; //通信端口号
int fd;
/*客户端信息的结构*/
typedef struct client1{
char name[20];
int sock;
} Client;
Client client[100]; //能同时容纳100个客户上线
int size = 0; //存放当前在线客户端数目
void fa(int signo){
printf("服务器出现异常,正在退出...\n");
sleep(3);
close(fd);
printf("服务器已关闭\n");
exit(0);
}
/*线程函数*/
void* task(void* p);
/*数据发送函数*/
void sendmsgtoALL(char* msg);
void init();
void start();
void closeServe();
int main(){
signal(SIGINT,fa);
init();
start();
closeServe();
}
void init(){
printf("服务器正在初始化...\n");
sleep(3);
/*创建socket描述符*/
fd = socket(AF_INET,SOCK_STREAM,0);
if (fd==-1) perror("socket"),exit(-1);
/*准备通信地址*/
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr(IP);
/*绑定*/
int res = bind(fd,(struct sockaddr*)&addr,sizeof(addr));
if(res==-1) perror("bind"),exit(-1);
/*监听*/
listen(fd,100);
printf("服务器初始化完毕!\n");
}
void start(){
printf("服务器正在启动...\n");
sleep(3);
printf("服务器启动成功!\n");
printf("等待客户端的连接....\n");
while(1){
/*创建连接上来的客户端通信地址*/
struct sockaddr_in from;
socklen_t len = sizeof(from);
int sockfd = accept(fd,(struct sockaddr*)&from,&len);
if(sockfd == -1) perror("accept"),exit(-1);
/*为连接上来的客户端开辟新的线程*/
client[size].sock = sockfd;
pthread_t p_id;
pthread_create(&p_id,0,task,(void*)&(client[size].sock));
}
}
void closeServe(){
printf("服务器正在关闭...\n");
sleep(3);
close(fd);
printf("服务器关闭成功!\n");
exit(0);
}
void* task(void* p){
int socktemp = *((int*)p);
char name[20] = {}; //用于接收用户名
char buf[100] = {};
int i,temp;
if(read(client[size].sock,name,sizeof(name))>0)
strcpy(client[size].name,name);
temp = size;
size++;
/*首次进入聊天室打印如下提示*/
char remind[100] = {};
sprintf(remind,"欢迎%s进入本聊天室..",client[size-1].name);
sendmsgtoALL(remind);
while(1){
if (read(socktemp,buf,sizeof(buf))<=0){
char remind1[100]={};
sprintf(remind1,"%s退出聊天室",client[temp].name);
sendmsgtoALL(remind1);
for(i=0;i
//用来分发消息的函数
void sendmsgtoALL(char * msg){
int i=0;
for(;i if(client[i].sock!=0){
printf("sendto****%d\n",client[i].sock);
send(client[i].sock,msg,strlen(msg),0);//
}
}
}
//
//
/*基于TCP协议的多线程聊天室客户端口*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
int fd;
char name[50];
char *IP = "192.168.1.100";
short PORT = 5555;
void init();
void start();
void* task(void* p);
void fa(int signo){
printf("正在退出...");
sleep(1);
close(fd);
exit(0);
}
int main(){
signal(SIGINT,fa); //将信号2注册为自定义函数,用于退出
printf("正在启动...\n");
sleep(3);
printf("启动成功,请输入用户名:");
scanf("%s",name);
init();
write(fd,name,strlen(name));
start();
}
void init(){
/*步骤和服务器端差不多*/
fd = socket(AF_INET,SOCK_STREAM,0);
if (fd==-1) perror("socket"),exit(-1);
/*创建通信地址*/
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr(IP);
/*连接服务器*/
int res = connect(fd,(struct sockaddr*)&addr,sizeof(addr));
if(res == -1) perror("connect"),exit(-1);
printf("连接服务器成功!\n");
}
void start(){
/*客户端除了要给服务器发送数据外,还要接收服务器的数据
而这两个步骤是并行的,所以我们在主线程中写,开辟的线程中读*/
pthread_t pid;
pthread_create(&pid,0,task,0);
char msg[100] = {};
while(1){
scanf("%s",msg);
write(fd,msg,strlen(msg));
/*必须把缓冲区清空*/
memset(msg,0,strlen(msg));
}
}
/*线程函数,用于读服务器发送过来的数据*/
void* task(void* p){
while(1){
char buf[100] = {};
if(read(fd,buf,sizeof(buf))<=0)
return;
printf("%s\n",buf);
memset(buf,0,sizeof(buf));
}
}
聊天室搭建完毕,值得注意的是我们的运行平台是linux而不是windows。