Linux下C语言多线程,网络通信简单聊天程序_第1页
Linux下C语言多线程,网络通信简单聊天程序_第2页
Linux下C语言多线程,网络通信简单聊天程序_第3页
Linux下C语言多线程,网络通信简单聊天程序_第4页
Linux下C语言多线程,网络通信简单聊天程序_第5页
免费预览已结束,剩余3页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、LinuxLinux 下 C C 语言多线程,网络通信简单聊天程序功能描述:程序应用多线程技术,可是实现 1 1 对 N N 进行网络通信聊天。但至今没想出合适的退出机制,除了用 Ctr+CCtr+C。出于演示目的,这里采用 UNIXUNIX 域协议(文件系统套接字):程序分为客户端和服务端。应用 selectselect 函数来实现异步的读写操作。先说一下服务端:首先先创建套接字,然后绑定,接下进入一个无限循环,用acceptaccept 函数,接受连接”请求,然后调用创建线程函数,创造新的线程,进入下一个循环。这样每当有一个新的连接”被接受都会创建一个新的线程,实现 1 1 对 N N 的

2、网络通信。在服务端程序中线程中用一个 bufferbuffer 读写,为了避免错误,这时就要给关键代码加上互斥锁work_mutexwork_mutex,具体见代码。国 E E 服务端代码1#include2#include3#include4#include5#include6#include7#include8#include/这里没有用二进制信号量可以删掉910 charbuffer1024;/读写用的区域11 sem_tbin_sem;/没用到的二进制信号量,可以删掉12 void*pthread_function(void*arg);/线程入口函数声明13 pthread_mutex

3、_twork_mutex;/声明互斥锁1415 intmain()16 intresult;/整数变量用来储存调用函数的返回值17 structsockaddr_unserver_address,client_address;/UNIX 域的套接字,server_address 用于服务端的监听,client_address 用于客户端连接后的套接字18 intclient_len;/连接后,accept 函数会把客户端的地址的长度储存在这19 intserver_socketfd,client_socketfd;/服务端和客户端的套接字文件描述符20pthread_ta_thread;/线程

4、 ID 标志21pthread_attr_tthread_attr;被我注释掉了,没用到,可以删掉。2223result=sem_init(&bin_sem,0,1);/初始化二进制信号量,因为用了互斥锁,所以没用到,可以删掉24if(result!=0)25perror(sem_init);26exit(EXIT_FAILURE);272829result=pthread_mutex_init(&work_mutex,NULL);初始化互斥锁30if(result!=0)31perror(pthread_mutex_init);32exit(EXIT_FAILURE);333435serve

5、r_socketfd=socket(AF_UNIX,SOCK_STREAM,0);/创建套接字,用 TCP 连接方式,出于演示目的只用 UNIX 域套接字。3637server_address.sun_family=AF_UNIX;38strcpy(server_address.sun_path,server_socket);3940unlink(server_socket);/在绑定之前,把以前存在当前目录下的套接字删除4142result=bind(server_socketfd,(structsockaddr*)&server_address,sizeof(server_address)

6、;/绑定43if(result!=0)44perror(bind);45exit(EXIT_FAILURE);4647个连接请求/线程的属性,后面可以看的,48result=listen(server_socketfd,5);/监听,最多允许 549if(result!=0)50perror(listen);51exit(EXIT_FAILURE);525354client_len=sizeof(client_address);55while(1)/开始进入无限循环56/*printf(Ifyouwanttoquit,pleaseenterquitn);57printf(Doyouwantto

7、acceptaconnectiongn);58memset(buffer,0,sizeof(buffer);59fgets(buffer,sizeof(buffer),stdin);60if(strncmp(quit,buffer,4)=0)break;*/6162client_socketfd=accept(server_socketfd,(structsockaddr*)&client_address,&client_len);/接受一个连接请求6364/*result=pthread_attr_init(&thread_attr);65if(result!=0)66perror(pthr

8、ead_attr_init);67exit(EXIT_FAILURE);6869result=pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED);70if(result!=0)71perror(pthread_attr_setdetachstate);72exit(EXIT_FAILURE);73*/74result=pthread_create(&a_thread,NULL,pthread_function,(void*)client_socketfd);/成功接受一个请求后,就会创建一个线程,然后主线程又进入

9、accept 函数,如果此时没有连接请求,那么主线程会阻塞75if(result!=0)76perror(pthread_create);77exit(EXIT_FAILURE);787980818283void*pthread_function(void*arg)/线程入口函数,每调用一次 pthread_create,都会创建一个新的线程84intfd=(int)arg;/把函数参数,即连接成功后的套接字,赋给 fd.85intresult;86fd_setread_fds;/文件描述符集合,用于 select 函数87intmax_fds;/文件描述符集合的最大数8889printf(%

10、didhasconnected!n,fd);90while(1)9192FD_ZERO(&read_fds);/清空集合93FD_SET(0,&read_fds);/将标准输入放入监听的文件描述符集合,这个用于读取标准输入,即键盘的输入94FD_SET(fd,&read_fds);/将连接后的客户文件描述符放入监听的文件描述符集合,这个用于向客户端读取数据95max_fds=fd+1;9697/sem_wait(&bin_sem);98pthread_mutex_lock(&work_mutex);/对关键区域上锁99printf(%dhasgetthelockn,fd);100result=

11、select(max_fds,&read_fds,(fd_set*)NULL,(fd_set*)NULL,(structtimeval*)NULL);/开始监听那些文件描述符出于可读状态101if(result1)102printf(select);103104if(FD_ISSET(0,&read_fds)/如果标准输入处于可读状态,说明键盘有所输入,将输入的数据存放在 buffer 中,然后向客户端写回,如果输入“quit”将会退出一个聊天线程读,那么读取存放在 buffer 中,然后显示出来,如果对方中断聊天,那么rememset(buffer,0,sizeof(buffer);resu

12、lt=read(fd,buffer,sizeof(buffer);if(result=-1)perror(read);exit(EXIT_FAILURE);elseif(result=0)printf(Theothersidehasterminalthec/sem_post(&bin_sem);pthread_mutex_unlock(&work_mutex);break;elseprintf(receivemessage:%s,buffer);138pthread_mutex_unlock(&work_mutex);/解锁sleep(1);/如果没有这一行,当前线程会一直占据 buffer.

13、105memset(buffer,0,sizeof(buffer);/保险起见,清零106107108109110111112113114115116117118119120fgets(buffer,if(strncmp(printf(sizeof(buffer),quit,buffer,stdin);4)=0)Youhaveterminaledthechatn);121/sem_post(&bin_sem);pthread_mutex_unlock(&work_mutex);break;elseresult=write(fd,buffer,if(result=-1)perror(write)

14、;exit(EXIT_FAILURE);if(FD_ISSET(fd,&read_fds)sizeof(buffer);/如果客户套接字符可sult=0122123124125126127128129hatn);130131132133134135136137139让当前线程暂停一秒可以实现 1 对 N 的功能140/sem_post(&bin_sem);141/sleep(1);142)143/printf(Iamheren);144close(fd);145pthread_exit(NULL);146147)148读者可以对比一下http:/ N N 个人进行聊天, 尽管有些 bug(bu

15、g(如果客户端对方回复太快太频繁, 服务端的锁就会切换来切换去,无法回复到正确的客户端)。客户端跟服务端很像,但比较简单。这里面就不注释了。这两个程序我都运行过。没什么基本大的问题。但是功能很不完善。还需改进。国 E E 客户端代码1 #include2 #include3 #include4 #include5 #include6 #include7 #include89 intmain()10 intresult;11 intsocketfd;12 intlen;13 structsockaddr_unaddress;14 fd_setread_fds,test_fds;15 intfd;

16、16 intmax_fds;17 charbuffer1024;1819 socketfd=socket(AF_UNIX,SOCK_STREAM,0);2021 address.sun_family=AF_UNIX;22 strcpy(address.sun_path,server_socket);23len=sizeof(address);2425result=connect(socketfd,(structsockaddr*)&address,len);26if(result=-1)27perror(connect);28exit(EXIT_FAILURE);293031FD_ZERO(&

17、read_fds);32FD_SET(0,&read_fds);33FD_SET(socketfd,&read_fds);34max_fds=socketfd+1;3536printf(Chatnow!n);3738while(1)39test_fds=read_fds;40result=select(max_fds,&test_fds,(fd_set*)NULif(result1)perror(select);exit(EXIT_FAILURE);if(FD_ISSET(0,&test_fds)memset(buffer,0,sizeof(buffer);/printf(send:);fgets(buffer,sizeof(buffer),stdin);if(strncmp(quit,buffer,4)=0)printf(nYouaregoingtoquitn);break;result=write(socketfd,buffer,sizeof(buffeif(result=-1)perror(write);exit(EXIT_FAILURE);if(FD_ISSET(socketfd,&test_fds)memset(buffer,0,sizeof(buffer);result=read(socketfd,buffer,s

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论