Linux C 网络编程——多线程的聊天室实现(服务器端)
2016-03-22 22:28
513 查看
服务器端的主要功能:
实现多用户群体聊天功能(此程序最多设定为10人,可进行更改),每个人所发送的消息其他用户均可以收到。用户可以随意的加入或退出(推出以字符串“bye”实现),服务器也可以进行关闭。
服务器端的程序结构:
总共有三个函数:主函数(main),实现服务器端的初始化,接受连接;消息处理函数(rcv_snd),接受某一用户的消息,将其进行简单处理之后发送给其他所有的用户;退出函数(quit),可实现服务器关停。
这三个函数分别从属于三个线程(准确说是大于等于三个,下面说明原因):main函数的作为诛仙程线程,又创建了一个退出函数所在的线程,以及每次接受到一个连接之后会新创建一个对此连接的消息进行处理的线程(多于三个的原因在此)。
具体代码实现如下:
[html]
view plain
copy
print?
#include<time.h>
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#define LISTENQ 5
#define MAXLINE 512
#define MAXMEM 10
#define NAMELEN 20
int listenfd,connfd[MAXMEM];//分别记录服务器端的套接字与连接的多个客户端的套接字
void quit();//服务器关闭函数
void rcv_snd(int n);//服务器接收并转发消息函数
int main()
{
pthread_t thread;
struct sockaddr_in servaddr,cliaddr;
socklen_t len;
time_t ticks;
char buff[MAXLINE];
//调用socket函数创建服务器端的套接字
printf("Socket...\n");
listenfd=socket(AF_INET,SOCK_STREAM,0);
if(listenfd<0)
{
printf("Socket created failed.\n");
return -1;
}
//调用bind函数使得服务器端的套接字与地址实现绑定
printf("Bind...\n");
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(6666);
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
{
printf("Bind failed.\n");
return -1;
}
//调用listen函数,将一个主动连接套接字变为被动的倾听套接字
//在此过程中完成tcp的三次握手连接
printf("listening...\n");
listen(listenfd,LISTENQ);
//创建一个线程,对服务器程序进行管理(关闭)
pthread_create(&thread,NULL,(void*)(&quit),NULL);
//记录空闲的客户端的套接字描述符(-1为空闲)
int i=0;
for(i=0;i<MAXMEM;i++)
{
connfd[i]=-1;
}
while(1)
{
len=sizeof(cliaddr);
for(i=0;i<MAXMEM;i++)
{
if(connfd[i]==-1)
{
break;
}
}
//调用accept从listen接受的连接队列中取得一个连接
connfd[i]=accept(listenfd,(struct sockaddr*)&cliaddr,&len);
ticks=time(NULL);
sprintf(buff,"% .24s \r \n",ctime(&ticks));
printf("%s Connect from: %s,port %d\n\n",buff,inet_ntoa(cliaddr.sin_addr.s_addr),ntohs(cliaddr.sin_port));
//针对当前套接字创建一个线程,对当前套接字的消息进行处理
pthread_create(malloc(sizeof(pthread_t)),NULL,(void*)(&rcv_snd),(void*)i);
}
return 0;
}
void quit()
{
char msg[10];
while(1)
{
scanf("%s",msg);
if(strcmp("quit",msg)==0)
{
printf("Byebye...\n");
close(listenfd);
exit(0);
}
}
}
void rcv_snd(int n)
{
char* ask="Your name please:";
char buff[MAXLINE];
char buff1[MAXLINE];
char buff2[MAXLINE];
char name[NAMELEN];
time_t ticks;
int i=0;
int retval;
//获取此进程对应的套接字用户的名字
write(connfd
,ask,strlen(ask));
int len;
len=read(connfd
,name,NAMELEN);
if(len>0)
{
name[len]=0;
}
//把当前用户的加入告知所有用户
strcpy(buff,name);
strcat(buff,"\tjoin in\0");
for(i=0;i<MAXMEM;i++)
{
if(connfd[i]!=-1)
{
write(connfd[i],buff,strlen(buff));
}
}
//接受当前用户的信息并将其转发给所有的用户
while(1)
{
if((len=read(connfd
,buff1,MAXLINE))>0)
{
buff1[len]=0;
//当当前用户的输入信息为“bye”时,当前用户退出
if(strcmp("bye",buff)==0)
{
close(connfd
);
connfd
=-1;
pthread_exit(&retval);
}
ticks=time(NULL);
sprintf(buff2,"%.24s\r\n",ctime(&ticks));
[html]
view plain
copy
print?
strcpy(buff,name);
strcat(buff,"\t");
strcat(buff,buff2);
strcat(buff,buff1);
for(i=0;i<MAXMEM;i++)
{
if(connfd[i]!=-1)
{
write(connfd[i],buff,strlen(buff));
}
}
}
}
实现多用户群体聊天功能(此程序最多设定为10人,可进行更改),每个人所发送的消息其他用户均可以收到。用户可以随意的加入或退出(推出以字符串“bye”实现),服务器也可以进行关闭。
服务器端的程序结构:
总共有三个函数:主函数(main),实现服务器端的初始化,接受连接;消息处理函数(rcv_snd),接受某一用户的消息,将其进行简单处理之后发送给其他所有的用户;退出函数(quit),可实现服务器关停。
这三个函数分别从属于三个线程(准确说是大于等于三个,下面说明原因):main函数的作为诛仙程线程,又创建了一个退出函数所在的线程,以及每次接受到一个连接之后会新创建一个对此连接的消息进行处理的线程(多于三个的原因在此)。
具体代码实现如下:
[html]
view plain
copy
print?
#include<time.h>
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#define LISTENQ 5
#define MAXLINE 512
#define MAXMEM 10
#define NAMELEN 20
int listenfd,connfd[MAXMEM];//分别记录服务器端的套接字与连接的多个客户端的套接字
void quit();//服务器关闭函数
void rcv_snd(int n);//服务器接收并转发消息函数
int main()
{
pthread_t thread;
struct sockaddr_in servaddr,cliaddr;
socklen_t len;
time_t ticks;
char buff[MAXLINE];
//调用socket函数创建服务器端的套接字
printf("Socket...\n");
listenfd=socket(AF_INET,SOCK_STREAM,0);
if(listenfd<0)
{
printf("Socket created failed.\n");
return -1;
}
//调用bind函数使得服务器端的套接字与地址实现绑定
printf("Bind...\n");
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(6666);
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
{
printf("Bind failed.\n");
return -1;
}
//调用listen函数,将一个主动连接套接字变为被动的倾听套接字
//在此过程中完成tcp的三次握手连接
printf("listening...\n");
listen(listenfd,LISTENQ);
//创建一个线程,对服务器程序进行管理(关闭)
pthread_create(&thread,NULL,(void*)(&quit),NULL);
//记录空闲的客户端的套接字描述符(-1为空闲)
int i=0;
for(i=0;i<MAXMEM;i++)
{
connfd[i]=-1;
}
while(1)
{
len=sizeof(cliaddr);
for(i=0;i<MAXMEM;i++)
{
if(connfd[i]==-1)
{
break;
}
}
//调用accept从listen接受的连接队列中取得一个连接
connfd[i]=accept(listenfd,(struct sockaddr*)&cliaddr,&len);
ticks=time(NULL);
sprintf(buff,"% .24s \r \n",ctime(&ticks));
printf("%s Connect from: %s,port %d\n\n",buff,inet_ntoa(cliaddr.sin_addr.s_addr),ntohs(cliaddr.sin_port));
//针对当前套接字创建一个线程,对当前套接字的消息进行处理
pthread_create(malloc(sizeof(pthread_t)),NULL,(void*)(&rcv_snd),(void*)i);
}
return 0;
}
void quit()
{
char msg[10];
while(1)
{
scanf("%s",msg);
if(strcmp("quit",msg)==0)
{
printf("Byebye...\n");
close(listenfd);
exit(0);
}
}
}
void rcv_snd(int n)
{
char* ask="Your name please:";
char buff[MAXLINE];
char buff1[MAXLINE];
char buff2[MAXLINE];
char name[NAMELEN];
time_t ticks;
int i=0;
int retval;
//获取此进程对应的套接字用户的名字
write(connfd
,ask,strlen(ask));
int len;
len=read(connfd
,name,NAMELEN);
if(len>0)
{
name[len]=0;
}
//把当前用户的加入告知所有用户
strcpy(buff,name);
strcat(buff,"\tjoin in\0");
for(i=0;i<MAXMEM;i++)
{
if(connfd[i]!=-1)
{
write(connfd[i],buff,strlen(buff));
}
}
//接受当前用户的信息并将其转发给所有的用户
while(1)
{
if((len=read(connfd
,buff1,MAXLINE))>0)
{
buff1[len]=0;
//当当前用户的输入信息为“bye”时,当前用户退出
if(strcmp("bye",buff)==0)
{
close(connfd
);
connfd
=-1;
pthread_exit(&retval);
}
ticks=time(NULL);
sprintf(buff2,"%.24s\r\n",ctime(&ticks));
#include<time.h> #include<stdio.h> #include<sys/socket.h> #include<netinet/in.h> #include<string.h> #define LISTENQ 5 #define MAXLINE 512 #define MAXMEM 10 #define NAMELEN 20 int listenfd,connfd[MAXMEM];//分别记录服务器端的套接字与连接的多个客户端的套接字 void quit();//服务器关闭函数 void rcv_snd(int n);//服务器接收并转发消息函数 int main() { pthread_t thread; struct sockaddr_in servaddr,cliaddr; socklen_t len; time_t ticks; char buff[MAXLINE]; //调用socket函数创建服务器端的套接字 printf("Socket...\n"); listenfd=socket(AF_INET,SOCK_STREAM,0); if(listenfd<0) { printf("Socket created failed.\n"); return -1; } //调用bind函数使得服务器端的套接字与地址实现绑定 printf("Bind...\n"); servaddr.sin_family=AF_INET; servaddr.sin_port=htons(6666); servaddr.sin_addr.s_addr=htonl(INADDR_ANY); if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0) { printf("Bind failed.\n"); return -1; } //调用listen函数,将一个主动连接套接字变为被动的倾听套接字 //在此过程中完成tcp的三次握手连接 printf("listening...\n"); listen(listenfd,LISTENQ); //创建一个线程,对服务器程序进行管理(关闭) pthread_create(&thread,NULL,(void*)(&quit),NULL); //记录空闲的客户端的套接字描述符(-1为空闲) int i=0; for(i=0;i<MAXMEM;i++) { connfd[i]=-1; } while(1) { len=sizeof(cliaddr); for(i=0;i<MAXMEM;i++) { if(connfd[i]==-1) { break; } } //调用accept从listen接受的连接队列中取得一个连接 connfd[i]=accept(listenfd,(struct sockaddr*)&cliaddr,&len); ticks=time(NULL); sprintf(buff,"% .24s \r \n",ctime(&ticks)); printf("%s Connect from: %s,port %d\n\n",buff,inet_ntoa(cliaddr.sin_addr.s_addr),ntohs(cliaddr.sin_port)); //针对当前套接字创建一个线程,对当前套接字的消息进行处理 pthread_create(malloc(sizeof(pthread_t)),NULL,(void*)(&rcv_snd),(void*)i); } return 0; } void quit() { char msg[10]; while(1) { scanf("%s",msg); if(strcmp("quit",msg)==0) { printf("Byebye...\n"); close(listenfd); exit(0); } } } void rcv_snd(int n) { char* ask="Your name please:"; char buff[MAXLINE]; char buff1[MAXLINE]; char buff2[MAXLINE]; char name[NAMELEN]; time_t ticks; int i=0; int retval; //获取此进程对应的套接字用户的名字 write(connfd ,ask,strlen(ask)); int len; len=read(connfd ,name,NAMELEN); if(len>0) { name[len]=0; } //把当前用户的加入告知所有用户 strcpy(buff,name); strcat(buff,"\tjoin in\0"); for(i=0;i<MAXMEM;i++) { if(connfd[i]!=-1) { write(connfd[i],buff,strlen(buff)); } } //接受当前用户的信息并将其转发给所有的用户 while(1) { if((len=read(connfd ,buff1,MAXLINE))>0) { buff1[len]=0; //当当前用户的输入信息为“bye”时,当前用户退出 if(strcmp("bye",buff)==0) { close(connfd ); connfd =-1; pthread_exit(&retval); } ticks=time(NULL); sprintf(buff2,"%.24s\r\n",ctime(&ticks));
[html]
view plain
copy
print?
strcpy(buff,name);
strcat(buff,"\t");
strcat(buff,buff2);
strcat(buff,buff1);
for(i=0;i<MAXMEM;i++)
{
if(connfd[i]!=-1)
{
write(connfd[i],buff,strlen(buff));
}
}
}
}
相关文章推荐
- 最简单的基于Flash的流媒体示例:网页播放器(HTTP,RTMP,HLS)
- HTTP学习笔记:HTTP报文
- HTTP学习笔记:URL与资源
- HTTP权威指南学习笔记:连接管理
- Linux网络基础命令
- [疯狂Java]网络:GET/POST请求、设置请求属性、获取响应属性
- 3.19Java基础知识:Socket编程全部,TCPIP
- RHCE7 搭建SAMBA服务实现目录网络共享
- Android网络编程之解析XML格式数据
- [TCPIP]代理arp
- 特殊的HttpApplication事件处理
- Linux-进程间通信(五): 网络套接字
- loadrunner简单使用——HTTP,WebService,Socket压力测试脚本编写
- Linux网络属性配置
- 三大家族轻松管理CentOS 7网络属性配置
- JAVA实现网络爬虫
- TCP通信和UDP通信练习
- RHCE7.0-搭建基于NFS网络文件系统服务
- 循环神经网络(RNN)反向传播算法(BPTT)理解
- Linux网络属性配置“三大家族”(ifcfg、iproute、配置文件)