最近在无聊完成了一个简单的基于select模型的匿名聊天室程序,均使用C++开发
服务器工作原理:
每接收一条客户端的信息,就将遍历所有的socket,并将该信息发给所有的客户端.
客户端使用两条线程,一个是接收服务端信息的线程,一个是等待阻塞输入的线程,获得输入时,将输入发送到服务器。
项目源码:https://github.com/coderguang/Chat
版本为v2.0的release.
其中ComLib也在github上
服务器核心代码:
int main(int argc,char **argv){ int i,counter,maxfd,sockfd,listenfd,connfd; int nready,client[FD_SETSIZE]; ssize_t n; fd_set rset,allset; char buf[MSGSIZE]; socklen_t clilen; struct sockaddr_in cliaddr; struct sockaddr_in servaddr; listenfd=Socket(AF_INET,SOCK_STREAM,0); bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family=AF_INET; servaddr.sin_port=htons(PORT); //servaddr.sin_port=htons(atoi(argv[0])); servaddr.sin_addr.s_addr=INADDR_ANY; Bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)); Listen(listenfd,10); maxfd=listenfd; //initialize counter=-1; for(i=0;i<FD_SETSIZE;i++){ client[i]=-1; } FD_ZERO(&allset); FD_SET(listenfd,&allset); for(;;){ rset=allset; nready=Select(maxfd+1,&rset,NULL,NULL,NULL); if(FD_ISSET(listenfd,&rset)){//new client connecton clilen=sizeof(cliaddr); connfd=Accept(listenfd,(struct sockaddr *)&cliaddr,&clilen); for(i=0;i<FD_SETSIZE;i++){ if(client[i]<0){ client[i]=connfd;//save the new sockfd break; } } if(i==FD_SETSIZE){ cout<<"sockfd set full!"<<endl; } FD_SET(connfd,&allset);//add new to set if(connfd>maxfd){ maxfd=connfd;//for select } if(i>counter){//max index in client[] counter=i; } if(nready<=0){ continue; //no more readable } } for(i=0;i<FD_SETSIZE;i++){//check all clients for data if((sockfd=client[i])<0){ continue; } if(FD_ISSET(sockfd,&rset)){ memset(buf,sizeof(buf),'\0'); if((n=Read(sockfd,buf,MSGSIZE))==0){ close(sockfd);//connection closed by client FD_CLR(sockfd,&allset); client[i]=-1; }else{ buf[n]='\0'; cout<<"get the msg:"<<buf<<endl; for(int j=0;j<FD_SETSIZE;j++){ if(client[j]!=-1) Writen(client[j],buf,n); } } if(nready<=0){ break; } } } } }
客户端核心代码:
<span style="font-size:18px;">int main(){ WORD mVersionRequested; WSADATA wsaData;//WSADATA结构被用来保存AfxSocketInit函数返回的WindowsSockets初始化信息。 int ret; SOCKET sClient; struct sockaddr_in saServer; bool fSuccess=true; //winSock 初始化 mVersionRequested=MAKEWORD(2,2);//WinSock dll的版本 ret=WSAStartup(mVersionRequested,&wsaData); if(ret!=0){ cout<<"WSASartup failed!"<<endl; getchar(); getchar(); exit(1); } if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2){ WSACleanup(); cout<<"invaild version"<<endl; getchar(); getchar(); exit(1); } sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sClient == INVALID_SOCKET){ WSACleanup(); cout << "socket failed" << endl; getchar(); getchar(); exit(0); } saServer.sin_family=AF_INET; saServer.sin_port=htons(port); saServer.sin_addr.S_un.S_addr=inet_addr(host); ret=connect(sClient,(struct sockaddr *)&saServer,sizeof(saServer)); if(ret==SOCKET_ERROR){ cout<<"连接失败!"<<endl; closesocket(sClient); WSACleanup(); getchar(); getchar(); exit(1); } thread recThread(Receive, sClient); thread sendThread(ChatInput,sClient); recThread.join(); sendThread.join(); cout << "over" << endl; closesocket(sClient); WSACleanup(); getchar(); getchar(); return 0; } </span>
一个应届生,没有服务端的工作经验,只有半年的U3D实习经验,要8K确实过了,还是太年轻,经验太少啊~~,其实8K只是期望,低点也是无所谓的,6K5我就接受啦~~下午三点笔试面试一直面到了总经理面,到了6点他们总经理还没有空,HR说等他们确定了之后再约,这个确定是神马意思~~~,看来要多投几份了~~~,不过还是挺喜欢9377的,离我现在住的走路地方只要5分钟路程~~~
do hard~~
—————————————————————————————————————————————————————————————————
//写的错误或者不好的地方请多多指导,可以在下面留言或者点击左上方邮件地址给我发邮件,指出我的错误以及不足,以便我修改,更好的分享给大家,谢谢。
转载请注明出处:http://blog.csdn.net/qq844352155
author:天下无双
Email:royalchen@royalchen.com
2015-6-30
于广州天河荷光路
——————————————————————————————————————————————————————————————————
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/qq844352155/article/details/46698109