void* RunFunc() { sockid = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); sockaddr_in addr; addr.sin_port = htons(_unPort); addr.sin_family = AF_INET; inet_aton("127.0.0.1",&(addr.sin_addr)); printf("begin to connect\n"); if(!connect(sockid,(sockaddr*)&addr,sizeof(addr))) { printf("connected succcss\n"); bool bCont = true; while(bCont) { if( Send() && Recv() ) { } else { bCont = false; } } } else { printf("connected failed %d\n",errno); } CloseSock(); Stop(); }
/** * @author ACM2012 * @param [in] pReadQueue 读队列控制块结构, ReadQueue 读队列控制块句柄,SockMark 套接字标志 * @note 函数的主要功能是从应用程序写队列中读取数据并传送到传输层。函数提取 */ void SockPool::WriteSock(HANDLE CH, unsigned int SockMark, HANDLE WriteQueue, PM pWriteQueue,HANDLE &SDestory) { bool closeflag = false; int readnum; while (SockMark2WriteState[SockMark]){ HANDLE NewNode = CreateFileMapping(HANDLE(0xFFFFFFFF), NULL, PAGE_READWRITE, 0, sizeof(Node), NULL); PN pNode = (PN)MapViewOfFile(NewNode, FILE_MAP_WRITE, 0, 0, sizeof(Node)); WaitForSingleObject(*SockMark2REvent[SockMark], INFINITE);///<等待传输层数据到来 ClearNode(pWriteQueue); if (!SockDataToNode(pNode, SockMark)) break; UnmapViewOfFile(pNode); SockMark2WEvent[SockMark]->SetEvent(); AddToTail(pWriteQueue,NewNode);///<添加数据到写队列 CloseHandle(NewNode); } ClearNode(pWriteQueue);///<释放写队列资源 CloseHandle(pWriteQueue->Head); CloseHandle(pWriteQueue->Tail); CloseHandle(pWriteQueue->Cur); UnmapViewOfFile(pWriteQueue); CloseHandle(WriteQueue); SockMark2WriteState.erase(SockMark); SockMark2WEvent.erase(SockMark); if (SockMark2State[SockMark]) CloseSock(SockMark); else SockMark2State[SockMark] = true; }
//--------------------------------------------------------------------------------------------------------------------------- //PostRecv() //return -1 when error , else return 0 //--------------------------------------------------------------------------------------------------------------------------- int CIocpServer::PostRecv(SOCKET_OBJ *sock, BUFFER_OBJ *recvobj) { WSABUF wbuf; DWORD bytes, flags; int rc; if(recvobj->buflen >= DEFAULT_BUFFER_SIZE) { #ifdef LOG_LEVEL2 Log_Server.Write("(->%d)接收缓冲溢出",sock->s); #endif CloseSock(sock); return -1; } recvobj->operation = OP_READ; wbuf.buf = recvobj->buf+recvobj->buflen; //将接收缓冲定位到原来数据的末尾 wbuf.len = DEFAULT_BUFFER_SIZE - recvobj->buflen; //重新设置可接受数据的长度 flags = 0; EnterCriticalSection(&sock->cs); rc = WSARecv( sock->s, &wbuf, 1, &bytes, &flags, &recvobj->ol, NULL ); if (rc == SOCKET_ERROR) { if (WSAGetLastError() != WSA_IO_PENDING) { #ifdef LOG_LEVEL2 Log_Server.Write("(->%d)PostRecv错误: %d",sock->s,WSAGetLastError()); #endif LeaveCriticalSection(&sock->cs); return SOCKET_ERROR; } } LeaveCriticalSection(&sock->cs); #ifdef LOG_STATUS InterlockedIncrement(&gIoCount); #endif return NO_ERROR; }
void DS::FreeSock(DS::SocketHandle sock) { CloseSock(sock); delete reinterpret_cast<SocketHandle_Private*>(sock); }
/** * @author ACM2012 * @param [in] CH 被服务程序句柄,pReadQueue 读队列控制块结构, ReadQueue 读队列控制块句柄,SockMark 套接字标志 * @note 函数的主要功能是从应用程序写队列中读取数据并传送到传输层。函数提取 */ void SockPool::ReadSock(HANDLE CH, unsigned int SockMark, HANDLE ReadQueue, PM pReadQueue,HANDLE &CDestory) { PN pCur = (PN)MapViewOfFile(pReadQueue->Cur, FILE_MAP_WRITE, 0, 0, sizeof(Node));//获取Cur映射内存块 transstruct AppData; HANDLE HData = NULL; portin myportsrc; CString myid; while (SockMark2ReadState[SockMark]) { ///<当状态变为false时退出 if (pCur->Next == NULL){ Sleep(100); continue; } CloseHandle(pReadQueue->Cur);//释放Cur DuplicateHandle(CH, pCur->Next, SH, &pReadQueue->Cur, NULL, true, DUPLICATE_SAME_ACCESS); UnmapViewOfFile(pCur); pCur = (PN)MapViewOfFile(pReadQueue->Cur, FILE_MAP_WRITE, 0, 0, sizeof(Node)); PN pNode = (PN)MapViewOfFile(pReadQueue->Cur, FILE_MAP_WRITE, 0, 0, sizeof(Node)); memset(&AppData, 0, sizeof(transstruct));///初始化为0 myid.Format(_T("%s %d"), AfxGetApp()->m_lpCmdLine,pNode->FuncID); //AfxMessageBox(myid); switch (pNode->FuncID){///获取当前命令类型 case SOCKBIND: Port2SockMark.erase(SockMark2Port[SockMark]); SockMark2Port.erase(SockMark); SockMark2Port[SockMark] = pNode->bindport; Port2SockMark[pNode->bindport] = SockMark; break; case SOCKACCEPT: memcpy(myportsrc.srcip, pNode->srcip, 20); myportsrc.srcport = pNode->srcport; myportsrc.dstport = SockMark2Port[SockMark]; PortIn2ScokMark[myportsrc] = pNode->AcceptSockMark; Port2PortOut[SockMark2Port[pNode->AcceptSockMark]] = pNode->dstport; break; case SOCKSEND: case SOCKSENDTO: ///<发送数据 memcpy(AppData.dstip, pNode->dstip, 20); AppData.dstport = pNode->dstport; AppData.datalength = pNode->DataLen;///<填充源端口 AppData.srcport = (Port2PortOut.find(SockMark2Port[SockMark]) == Port2PortOut.end()) ? SockMark2Port[SockMark] : Port2PortOut[SockMark2Port[SockMark]]; AppData.function = pNode->FuncID; DuplicateHandle(CH, pNode->Data, SH, &HData, NULL, true, DUPLICATE_SAME_ACCESS); AppData.data = (char *)MapViewOfFile(HData, FILE_MAP_WRITE, 0, 0, pNode->DataLen); AfxGetApp()->m_pMainWnd->SendMessage(TRANSTOIP, (WPARAM)&AppData, (LPARAM)pNode->FuncID); break; case SOCKCONNECT: case SOCKCLOSE: memcpy(AppData.dstip, pNode->dstip, 20); AppData.dstport = pNode->dstport; AppData.srcport = SockMark2Port[SockMark]; AppData.function = pNode->FuncID; //if (pNode->FuncID == SOCKCONNECT) AfxGetApp()->m_pMainWnd->SendMessage(TRANSTOIP, (WPARAM)&AppData, (LPARAM)pNode->FuncID); break; case SOCKLISTEN: AppData.srcport = SockMark2Port[SockMark]; AppData.function = pNode->FuncID; AfxGetApp()->m_pMainWnd->SendMessage(TRANSTOIP, (WPARAM)&AppData, (LPARAM)pNode->FuncID); break; default: break; } if (AppData.data != NULL){ UnmapViewOfFile(AppData.data); AppData.data = NULL; } if (HData != NULL){ CloseHandle(HData); HData = NULL; } if (pNode->FuncID == SOCKCLOSE){ sockconnum--; UnmapViewOfFile(pNode); break; } UnmapViewOfFile(pNode); pReadQueue->cid++; } UnmapViewOfFile(pCur); ///<释放读队列资源 SockMark2ReadState.erase(SockMark); UnmapViewOfFile(pReadQueue); CloseHandle(ReadQueue); ReleaseSemaphore(CDestory,1,NULL); if (SockMark2State[SockMark]) CloseSock(SockMark); else SockMark2State[SockMark] = true; }
//如果发送队列存在,Send()首先尝试将数据添加到队列的最后一个BufferOBJ.如果BufferOBJ的可用空间不足, //Send()将开辟一个新的BufferOBJ用于发送.当发送队列为空时,Send()将调用PostSend()立即提交一个发送操作 // int CIocpServer::Send(SOCKET_OBJ *sock,const void * buffer,int len)//发送向客户端数据 { _ASSERTE(len <= DEFAULT_BUFFER_SIZE*MAX_UNSENDS_COUNT && len > 0); if(sock == NULL || len > DEFAULT_BUFFER_SIZE*MAX_UNSENDS_COUNT || len <= 0) return -1; BUFFER_OBJ * tmpbuf; int rc=NO_ERROR; #ifdef DEBUG_IOCP _ASSERTE(sock->onclosed == 0); //已经调用过OnClose()还发? _ASSERTE(sock->freeed == 0); //已经free掉了! #endif InterlockedIncrement(&sock->sending_count); //为了安全的freeobj if( ( sock->flag_close == 0 ) || (sock->s == INVALID_SOCKET) ) { InterlockedDecrement(&sock->sending_count); return -1; } int i=0; int len2=len; char *buf2; if(len2 > DEFAULT_BUFFER_SIZE) len2 = DEFAULT_BUFFER_SIZE; LOCK(&sock->cs); tmpbuf = sock->sendobj; if(tmpbuf == NULL) { //发送队列为空 tmpbuf = GetBufferObj(); #ifdef DEBUG_IOCP tmpbuf->sclient = sock->s; #endif memcpy(tmpbuf->buf,buffer,len2); tmpbuf->buflen = len2; rc = PostSend(sock,tmpbuf); if(rc == 0) sock->sendobj = tmpbuf; else FreeBufferObj(tmpbuf); } else { while(tmpbuf->next) { tmpbuf = tmpbuf->next; i++; } if(i > MAX_UNSENDS_COUNT) { rc = -1; CloseSock(sock); } else { if(tmpbuf->buflen + len2 > DEFAULT_BUFFER_SIZE) { tmpbuf->next = GetBufferObj(); tmpbuf = tmpbuf->next; } memcpy(tmpbuf->buf+tmpbuf->buflen,buffer,len2); tmpbuf->buflen += len2; } } len -= len2; buf2 = (char *)buffer+len2; while(rc == 0 && len >0) { len2 = len; if(len2 > DEFAULT_BUFFER_SIZE) len2 = DEFAULT_BUFFER_SIZE; tmpbuf->next = GetBufferObj(); tmpbuf = tmpbuf->next; memcpy(tmpbuf->buf,buf2,len2); tmpbuf->buflen = len2; len -= len2; buf2 += len2; i++; if(i > MAX_UNSENDS_COUNT) { #ifdef LOG_LEVEL1 Log_Server.Write("Send(): 发送失败(当前用户的发送队列超出 %d!",MAX_UNSENDS_COUNT); #endif rc = -1; break; } } UNLOCK(&sock->cs); InterlockedDecrement(&sock->sending_count); return rc; //注意:在PostSend()里面,buflen被设置为DEFAULT_BUFFER_SIZE,Send()调用时候的数据不会添加到正在发送的BufferObj后面 }