下面是服务器接受函数的代码:

如果是某个客户端第一次连接服务器,则建立握手先,以后,该连接除非重新连接服务器再,则不需要握手动作,做普通SOCKET通信

但是,下面代码作判断时,服务器只能与一个客户端建立连接,其他客户端就不能再连接上了,服务建立握手...

当多个客户端存在时,如何判断每一个客户端是否是第一次与服务器连接,以便建立握手?


//receivedata
voidRecvData(intfd,intevents,void*arg)
{
unsignedcharret_len;
unsignedcharsend_str[254];
structmyevent_s*ev=(structmyevent_s*)arg;
intlen,i;

memset(ev->buff,0,REQUEST_LEN_MAX);
len=recv(fd,ev->buff,sizeof(ev->buff),0);
//printf("---------------------\n");
printf("recvdatalen:%d\n",len);
//printf("---------------------\n");
//printf("recvdatacontent:%s\n",ev->buff);
printf("\n");
if(len<480){
//printf("recvdatacontent:\n");
for(i=0;i<len;i++)
printf("%02x",ev->buff[i]);
}

printf("\n");
if((0==connected))//目前只能接受一个客户端的连接握手,当第二个客户端请求连接时,就走不到握手协议这里,也就无法建立连接....
{
printf("shakehandisok%d\n",fd);
//printf("read:%d\n%s\n",len,ev->buff);
secWebSocketKey=computeAcceptKey(ev->buff);
shakeHand(fd,secWebSocketKey);
connected=1;
//printf("22222connectedis:%d\n",connected);
//continue;
}
/*
data=analyData(ev->buff,len);
printf("dataconent:%s\n",ev->buff);
printf("datalen:%d\n",len);
response(fd,data);
*/
if(len<254){
ret_len=analyData_2(ev->buff,len,send_str);

//printf("254content:\n");
//for(i=0;i<ret_len;i++)
//printf("%02x",send_str[i]);
}
if(len==6&ev->buff[0]==0x88)//页面上断开连接
{
//printf("3333connectedis:%d\n",connected);
connected=0;
close(ev->fd);
printf("[fd=%d]pos[%d],closedgracefully.\n",fd,ev-g_Events);
//printf("4444connectedis:%d\n",connected);
}
if(len>0)
{
ev->buff[0]=0x81;
ev->buff[1]=12;
ev->buff[2]=0x46;
ev->buff[3]=0x30;
ev->buff[4]=0x30;
ev->buff[5]=0x36;
ev->buff[6]=0x45;
ev->buff[7]=0x45;
ev->buff[8]=0x30;
ev->buff[9]=0x31;
ev->buff[10]=0x32;
ev->buff[11]=0x33;
ev->buff[12]=0x42;
ev->buff[13]=0x43;
ev->buff[14]=0x42;
ev->buff[15]=0x43;

ev->len+=len;
printf("\n");
//ev->buff[0]=buffer[0];
//ev->buff[1]=buffer[1];
//memcpy(ev->buff,buffer,buffer[1]+2);
ev->len=14;
ev->call_back=SendData;
//changetosendevent
//EventSet(ev,fd,SendData,ev);
EventAdd(g_epollFd,EPOLLOUT,ev);
}
elseif(len==0)
{
close(ev->fd);
printf("[fd=%d]pos[%d],closedgracefully.\n",fd,ev-g_Events);
}
else
{
close(ev->fd);
printf("recv[fd=%d]error[%d]:%s\n",fd,errno,strerror(errno));
}
}

7 个解决方案

#1


相对全一点的代码,代码都是来自网络,目前这样方式,只能接受一个客户端连接,并交互通信。

如何在客户端建立连接时,为每个客户端,标记一个状态,如果是第一次连接,则标记一个状态,以便完成握手动作,
握手后,修改状态,直到该客户端关闭连接再恢复该状态,,方便该客户端下次连接服务器以完成握手。




#defineREQUEST_LEN_MAX1024
#defineDEFEULT_SERVER_PORT8000
#defineWEB_SOCKET_KEY_LEN_MAX256
#defineRESPONSE_HEADER_LEN_MAX1024
#defineLINE_MAX256
#defineHOST_IP_ADDRESS_TCP"192.168.34.52"
#defineMAX_EVENTS500
#defineHOST_PORT_TCP4530

intconnected=0;//0:notconnect.1:connected.

structmyevent_s
{
intfd;
void(*call_back)(intfd,intevents,void*arg);
intevents;
void*arg;
intstatus;//1:inepollwaitlist,0notin
unsignedcharbuff[1024];//recvdatabuffer
intlen,s_offset;
longlast_active;//lastactivetime
};
//setevent
voidEventSet(structmyevent_s*ev,intfd,void(*call_back)(int,int,void*),void*arg)
{
ev->fd=fd;
ev->call_back=call_back;
ev->events=0;
ev->arg=arg;
ev->status=0;
bzero(ev->buff,sizeof(ev->buff));
ev->s_offset=0;
ev->len=0;
ev->last_active=time(NULL);
}
//add/modaneventtoepoll
voidEventAdd(intepollFd,intevents,structmyevent_s*ev)
{
structepoll_eventepv={0,{0}};
intop;
epv.data.ptr=ev;
epv.events=ev->events=events;
if(ev->status==1){
op=EPOLL_CTL_MOD;
}
else{
op=EPOLL_CTL_ADD;
ev->status=1;
}
if(epoll_ctl(epollFd,op,ev->fd,&epv)<0)
printf("EventAddfailed[fd=%d],evnets[%d]\n",ev->fd,events);
else
printf("EventAddOK[fd=%d],op=%d,evnets[%0X],status:[%d]\n",ev->fd,op,events,ev->status);
}
//deleteaneventfromepoll
voidEventDel(intepollFd,structmyevent_s*ev)
{
structepoll_eventepv={0,{0}};
if(ev->status!=1)return;
epv.data.ptr=ev;
ev->status=0;
epoll_ctl(epollFd,EPOLL_CTL_DEL,ev->fd,&epv);
}
intg_epollFd;
structmyevent_sg_Events[MAX_EVENTS+1];//g_Events[MAX_EVENTS]isusedbylistenfd
voidRecvData(intfd,intevents,void*arg);
voidSendData(intfd,intevents,void*arg);

//acceptnewconnectionsfromclients
voidAcceptConn(intfd,intevents,void*arg)
{
structsockaddr_insin;
socklen_tlen=sizeof(structsockaddr_in);
intnfd,i;
//accept
if((nfd=accept(fd,(structsockaddr*)&sin,&len))==-1)
{
if(errno!=EAGAIN&&errno!=EINTR)
{
}
printf("%s:accept,%d",__func__,errno);
return;
}
do
{
for(i=0;i<MAX_EVENTS;i++)
{
if(g_Events[i].status==0)
{
break;
}
}
if(i==MAX_EVENTS)
{
printf("%s:maxconnectionlimit[%d].",__func__,MAX_EVENTS);
break;
}
//setnonblocking
intiret=0;
if((iret=fcntl(nfd,F_SETFL,O_NONBLOCK))<0)
{
printf("%s:fcntlnonblockingfailed:%d",__func__,iret);
break;
}
//addareadeventforreceivedata
EventSet(&g_Events[i],nfd,RecvData,&g_Events[i]);
EventAdd(g_epollFd,EPOLLIN,&g_Events[i]);
}while(0);

printf("newconn%s,%d,time:%ld,pos:%d\n",inet_ntoa(sin.sin_addr),
ntohs(sin.sin_port),g_Events[i].last_active,i);
}
//receivedata
//帖子内容大小有限制,放主贴里了

//senddata
voidSendData(intfd,intevents,void*arg)
{
structmyevent_s*ev=(structmyevent_s*)arg;
intlen,i;
//senddata
len=send(fd,ev->buff+ev->s_offset,ev->len-ev->s_offset,0);
if(len>0)
{
//printf("send[fd=%d],[%d<->%d]%s\n",fd,len,ev->len,ev->buff);
printf("senddatais:\n");
for(i=0;i<ev->buff[1]+2;i++)
printf("%02X",ev->buff[i]);
printf("\n");
ev->s_offset+=len;
if(ev->s_offset==ev->len)
{
//changetoreceiveevent
EventDel(g_epollFd,ev);
EventSet(ev,fd,RecvData,ev);
EventAdd(g_epollFd,EPOLLIN,ev);
}
}
else
{
close(ev->fd);
EventDel(g_epollFd,ev);
printf("send[fd=%d]error[%d]\n",fd,errno);
}
}

voidInitListenSocket(intepollFd,shortport,char*ip)
{
intlistenFd=socket(AF_INET,SOCK_STREAM,0);
fcntl(listenFd,F_SETFL,O_NONBLOCK);//setnon-blocking
printf("serverlistenfd=%d\n",listenFd);
EventSet(&g_Events[MAX_EVENTS],listenFd,AcceptConn,&g_Events[MAX_EVENTS]);
//addlistensocket
EventAdd(epollFd,EPOLLIN,&g_Events[MAX_EVENTS]);
//bind&listen
structsockaddr_insin;
bzero(&sin,sizeof(sin));
sin.sin_family=AF_INET;
//sin.sin_addr.s_addr=INADDR_ANY;
//sin.sin_addr.s_addr=inet_addr(HOST_IP_ADDRESS_TCP);
sin.sin_addr.s_addr=inet_addr(ip);
sin.sin_port=htons(port);
bind(listenFd,(structsockaddr*)&sin,sizeof(sin));
listen(listenFd,5);
printf("serveripis:%s\n",ip);
}

intmain(intargc,char*argv[])
{
structsockaddr_inservaddr,cliaddr;
socklen_tcliaddr_len;
intlistenfd,connfd;
charbuf[REQUEST_LEN_MAX];
char*data;
charstr[INET_ADDRSTRLEN];
char*secWebSocketKey;
inti,n;
//intconnected=0;//0:notconnect.1:connected.

intport=DEFEULT_SERVER_PORT;

if(argc>1)
{
port=atoi(argv[1]);
}
if(port<=0||port>0xFFFF)
{
printf("Port(%d)isoutofrange(1-%d)\n",port,0xFFFF);
return;
}
//createepoll///////////////////////
g_epollFd=epoll_create(MAX_EVENTS);
if(g_epollFd<=0)printf("createepollfailed.%d\n",g_epollFd);
//create&bindlistensocket,andaddtoepoll,setnon-blocking
InitListenSocket(g_epollFd,HOST_PORT_TCP,HOST_IP_ADDRESS_TCP);
//eventloop
structepoll_eventevents[MAX_EVENTS];
printf("serverrunning:port[%d]\n",HOST_PORT_TCP);
intcheckPos=0;
/////////////////////////////////

while(1)
{

//waitforeventstohappen
intfds=epoll_wait(g_epollFd,events,MAX_EVENTS,1000);
if(fds<0){
printf("epoll_waiterror,exit\n");
break;
}
for(i=0;i<fds;i++){
structmyevent_s*ev=(structmyevent_s*)events[i].data.ptr;
if((events[i].events&EPOLLIN)&&(ev->events&EPOLLIN))//readevent
{
ev->call_back(ev->fd,events[i].events,ev->arg);
}
if((events[i].events&EPOLLOUT)&&(ev->events&EPOLLOUT))//writeevent
{
ev->call_back(ev->fd,events[i].events,ev->arg);
}
}
}//while
close(connfd);
}

更多相关文章

  1. 问一个高深的问题,静态html页面如何接收来自服务器的参数?
  2. golang写服务端程序,作为文件上传与下载的服务器。配合HTML5以网
  3. Html--树莓派作为Web服务器
  4. HTML5 Web Sockets与代理服务器交互
  5. 如何用c#获取服务器端元素的innerhtml(内部有另一个服务器端控件)
  6. 服务器数据库系列 - 日志系列 - Nginx日志
  7. MAMP服务器正在运行,但显示“哎呀! Google Chrome无法找到localhos
  8. Apache服务器压缩和利用浏览缓存问题
  9. 什么是客户端准备语句?

随机推荐

  1. Linux中mprotect()函数的用法
  2. Linux cat 命令源码剖析
  3. Apache性能调节(摘自于Apache经典实例)
  4. Linux搭载ISO镜像为本地yum源
  5. Linux内存管理 (10)缺页中断处理
  6. linux shell脚本指令
  7. PowerPC平台 linux移植一
  8. Linux 软件安装到 /usr,/usr/local/ 还是
  9. 请问有谁知道linux上生成的共享库中,使用n
  10. linux kernal oom killer 学习