#include "StdAfx.h" #include #include #include "So7_TCPIP_Server.h" const int WSA_MAJOR_VERSION = 1; const int WSA_MINOR_VERSION = 1; #define WSA_VERSION MAKEWORD(WSA_MAJOR_VERSION, WSA_MINOR_VERSION) #define SOCKADDR_LEN sizeof(SOCKADDR_IN) const BYTE CommHeader[]={0x46,0x49,0x4E,0x53}; const BYTE HandShaking[]={0X46,0X49,0X4E,0X53,0X00,0X00,0X00,0X10,0X00,0X00,0X00,0X01,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0X00,0X00,0X00,0X05}; const BYTE DRW_SData[]={0X46,0X49,0X4E,0X53,0X00,0X00,0X00,0X18,0X00,0X00,0X00,0X02,0X00,0X00,0X00,0X00,0XC0,0X00,0X02,0X00,0X03,0X00,0X00,0X05,0X00,0XFF,0X01,0X01,0X00,0X00}; const int DRW_SDataIndexDataSize=7; const int DRW_SDataIndexData=30; const int DRW_RDataIndexDA1=20; const int DRW_RDataIndexSA1=23; const int DRW_RDataIndexCMD1=26; const int DRW_RDataIndexCMD2=27; const int DRW_RDataIndexAddr1=29; const int DRW_RDataIndexAddr2=30; const int DRW_RDataIndexCh1=32; const int DRW_RDataIndexCh2=33; const int DRW_RDataIndexData=34; const int DRW_RDataCCLen=0x1A; const int DRW_RSDataIndexBufSize1=6; const int DRW_RSDataIndexBufSize2=7; struct_so7_tcpip_buff CSo7_TCPIP_Server::m_TCPIPBuf[lChannelSize]; s_tcpip_state CSo7_TCPIP_Server::m_TCPIPServerState; //================================================================ CSo7_TCPIP_Server::CSo7_TCPIP_Server() { m_hMsgWnd=NULL; m_ServerStarted=FALSE; m_Socket=INVALID_SOCKET; m_SreverIPAddress; m_iServerPortNumber=static_cast(0); for (int i=0;ih_addr_list[0],sizeof(in_addr)); _IPAddress=m_SreverIPAddress; first = FALSE; } _IPAddress=m_SreverIPAddress; return TRUE; } //================================================================ BOOL CSo7_TCPIP_Server::CreateAndListen() { if(m_Socket == INVALID_SOCKET) ::closesocket(m_Socket); // 创建套节字 m_Socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(m_Socket == INVALID_SOCKET) return FALSE; // 填写要关联的本地地址 sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(m_iServerPortNumber); sin.sin_addr.s_addr = INADDR_ANY; // 绑定端口 if(::bind(m_Socket, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR) { return FALSE; } // 设置socket为窗口通知消息类型 ::WSAAsyncSelect(m_Socket, m_hMsgWnd, WM_SOCKET, FD_ACCEPT|FD_CLOSE); // 进入监听模式 ::listen(m_Socket, 5); return TRUE; } //================================================================ BOOL CSo7_TCPIP_Server::AddClient(SOCKET s) { if(m_nClients < MAX_SOCKET) { m_ClientSocket[m_nClients++] = s; return TRUE; } return FALSE; } //================================================================ void CSo7_TCPIP_Server::RemoveClient(SOCKET s) { BOOL bFind = FALSE; int i(0); for(i=0; i>8) & 0x0ff; m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexData+2*i+1]=iData & 0x0ff; } m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexDataSize]=static_cast(DRW_SDataIndexData+2*_datasize); m_TCPIPBuf[CH_SEND]._size=sizeof(HandShaking); SendBuffer(); return TRUE; } //================================================================ BOOL CSo7_TCPIP_Server::Response_Sensor_State(short _datasize) { if(m_ClientSocket[m_nActiveClient] == INVALID_SOCKET) { return FALSE; } m_ClearSendBuf(); memcpy(m_TCPIPBuf[CH_SEND]._buffer,DRW_SData,sizeof(DRW_SData)); for (int i=0;i<_datasize;i++) { m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexData+i]=m_TCPIPServerState._PLCSensorState[i]; } m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexDataSize]=static_cast(DRW_SDataIndexData+2*_datasize); m_TCPIPBuf[CH_SEND]._size=DRW_SDataIndexData+2*_datasize; SendBuffer(); return TRUE; } //================================================================ BOOL CSo7_TCPIP_Server::Response_CCD_DATA(short _Addr,short _datasize) { if(m_ClientSocket[m_nActiveClient] == INVALID_SOCKET) { return FALSE; } m_ClearSendBuf(); memcpy(m_TCPIPBuf[CH_SEND]._buffer,DRW_SData,sizeof(DRW_SData)); int iData(0); for (int i=_Addr;i<_Addr+_datasize;i++) { iData=m_CCDData[i]; m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexData+2*i]=(iData>>8) & 0x0ff; m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexData+2*i+1]=iData & 0x0ff; } m_TCPIPBuf[CH_SEND]._buffer[DRW_SDataIndexDataSize]=static_cast(DRW_SDataIndexData+2*_datasize); m_TCPIPBuf[CH_SEND]._size=DRW_SDataIndexData+2*_datasize; SendBuffer(); return TRUE; } //================================================================ BOOL CSo7_TCPIP_Server::_Send_Cmd_Write_State() { if(m_ClientSocket[m_nActiveClient] == INVALID_SOCKET) { return FALSE; } m_ClearSendBuf(); m_TCPIPBuf[CH_SEND]._size=0; SendBuffer(); return TRUE; } //================================================================ LRESULT CSo7_TCPIP_Server::OnSocket(WPARAM wParam, LPARAM lParam) { // 取得有事件发生的套节字句柄 SOCKET s = wParam; // 查看是否出错 int errorCode = WSAGETSELECTERROR(lParam); if(errorCode) { RemoveClient(s); ::closesocket(s); return errorCode; } int event = WSAGETSELECTEVENT(lParam); switch(event) { case FD_ACCEPT: { if(m_nClients < MAX_SOCKET) { SOCKET client = ::accept(s, NULL, NULL); ::WSAAsyncSelect(client,m_hMsgWnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE); AddClient(client); } else { AfxMessageBox(_T("连接客户太多!")); }; ::PostMessage(m_hMsgWnd,WM_TCPIP_MSG,FD_ACCEPT,0); } break; case FD_READ: { UpdateActiveClient(s); m_ProcessSocketReadEvent(s); } break; case FD_WRITE: //This event happens when the tcp buffers are ready for another send. //So if there is not enough room for the first write the event will happen //and then the buffers are ready for more. m_ProcessSocketWriteEvent(); ::PostMessage(m_hMsgWnd,WM_TCPIP_MSG,FD_WRITE,0); break; case FD_CLOSE: { RemoveClient(s); ::closesocket(s); ::PostMessage(m_hMsgWnd,WM_TCPIP_MSG,FD_CLOSE,0); } break; } return 0; } //================================================================ void CSo7_TCPIP_Server::m_ClearSendBuf(void) { int i; for(i=0;i=m_TCPIPBuf[CH_SEND]._size) { m_TCPIPBuf[CH_SEND]._size = 0; m_TCPIPBuf[CH_SEND]._CompletedSize = 0; m_TCPIPBuf[CH_SEND]._hProtoPending=FALSE; break; } } } //================================================================ void CSo7_TCPIP_Server::m_ProcessSocketWriteEvent(void) { int errorCode, numBytesSent; SOCKET s = m_Socket; if(m_TCPIPBuf[CH_SEND]._size <= 0) return; char* sendBuf = m_TCPIPBuf[CH_SEND]._buffer; while(1) { numBytesSent = send(s, &(sendBuf[m_TCPIPBuf[CH_SEND]._CompletedSize]), m_TCPIPBuf[CH_SEND]._size-m_TCPIPBuf[CH_SEND]._CompletedSize, 0); if(numBytesSent == SOCKET_ERROR) { errorCode = WSAGetLastError(); if(errorCode == WSAEWOULDBLOCK) { return; //Should get a FD_WRITE event if this happens. Send the rest from there. } else { //showSocketError(errorCode); return; } } else { m_TCPIPBuf[CH_SEND]._CompletedSize += numBytesSent; } if(m_TCPIPBuf[CH_SEND]._CompletedSize>=m_TCPIPBuf[CH_SEND]._size) { m_TCPIPBuf[CH_SEND]._CompletedSize = 0; m_ClearSendBuf(); break; } } } //================================================================ void CSo7_TCPIP_Server::m_ProcessSocketReadEvent(SOCKET s) { int bytesReceived=0; int errorCode; bytesReceived = recv(s, &(m_TCPIPBuf[CH_RECV]._buffer[0]), TCPIP_MAX_BUFF_SIZE, 0); if(bytesReceived == SOCKET_ERROR) { errorCode = WSAGetLastError(); if (errorCode == WSAEWOULDBLOCK) { //have to wait for the next receive event return; } else { //showSocketError(errorCode); return; } } m_TCPIPBuf[CH_RECV]._CompletedSize += bytesReceived; m_TCPIPBuf[CH_RECV]._size = m_TCPIPBuf[CH_RECV]._CompletedSize; int iPara(0); if (strstr(m_TCPIPBuf[CH_RECV]._buffer, "FINS")) { if (m_TCPIPBuf[CH_RECV]._buffer[7]==0x0C)//handshake { Response_Handshake(); iPara=RESPONSE_HANDSHAKE; } else if (m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexCMD1]==0x01 &&m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexCMD2]==0x01) { short iAddr=(m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexAddr1]<<8)+m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexAddr2]; short iDataSize=(m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexCh1]<<8)+m_TCPIPBuf[CH_RECV]._buffer[DRW_RDataIndexCh2]; if (iAddr>=20000) { iPara=RESPONSE_READ_ERRCODE; } else if (iAddr>=10000) { Response_CCD_DATA((iAddr-10060),iDataSize); iPara=RESPONSE_READ_CCD_DATA; } else if (iAddr>=8000) { iPara=RESPONSE_WRITE_PLC_STATE; } else if (iAddr>=5000) { Response_PLC_State(1); iPara=RESPONSE_READ_PLC_STATE; } else { iPara=RESPONSE_UNKNOWN; } } } m_TCPIPBuf[CH_RECV]._CompletedSize = 0; m_TCPIPBuf[CH_RECV]._hProtoPending=FALSE; ::PostMessage(m_hMsgWnd,WM_TCPIP_MSG,FD_READ,iPara); }