📄 msgserver.cpp
字号:
/* * Copyright (C) 2004 Sun Microsystems, Inc. All rights reserved. Use is * subject to license terms. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ #include <stdio.h>#include <string.h>#include "MsgServer.h"#include "Message.h"#include "Util.h"MsgServer gMessenger;#ifdef WIN32CRITICAL_SECTION CriticalSection; #elsepthread_mutex_t gServerMutex;#endifint MsgServer::mPort = 0;MsgServer::MsgServer(){#ifdef WIN32 WSADATA wsaData; if (WSAStartup(WINSOCK_VERSION, &wsaData)) { WBTRACE("Can't load Windows Sockets DLL!\n"); }#endif mFailed = 1; mCounter = 0; mHandler = NULL; mSendBuffer = new char[BUFFER_SIZE]; mRecvBuffer = new char[BUFFER_SIZE]; // predefine the long receiver buffer. If it's not big enough, // alloc more space. mLongRecvBufferSize = BUFFER_SIZE * 4; mLongRecvBuffer = new char[mLongRecvBufferSize]; mSendBuffer[0] = mRecvBuffer[0] = mLongRecvBuffer[0] = 0; int i; mTriggers = new Trigger[MAX_TRIGGER]; for (i = 0; i < MAX_TRIGGER; i++) { mTriggers[i].mInstance = EMPTY_TRIGGER; } mServerSock = -1; mMsgSock = -1; FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds); #ifdef WIN32 InitializeCriticalSection(&CriticalSection);#else pthread_mutex_init(&gServerMutex,NULL);#endif}MsgServer::~MsgServer(){#ifdef WIN32 DeleteCriticalSection(&CriticalSection);#else pthread_mutex_destroy(&gServerMutex);#endif delete [] mSendBuffer; delete [] mRecvBuffer; delete [] mLongRecvBuffer; delete [] mTriggers; WBTRACE("Closing socket ...\n"); if (mServerSock >= 0) {#ifdef WIN32 closesocket(mServerSock);#else close(mServerSock);#endif } if (mMsgSock >= 0) {#ifdef WIN32 closesocket(mMsgSock);#else close(mMsgSock);#endif }#ifdef WIN32 WSACleanup();#endif}int MsgServer::CreateServerSocket(){ u_long nbio = 1; int bReuseaddr = 1; mServerSock = socket(AF_INET, SOCK_STREAM, 0);#ifdef WIN32 if (mServerSock == INVALID_SOCKET) {#else if (mServerSock < 0) {#endif WBTRACE("socket failed!"); goto failed; }#ifdef WIN32 ioctlsocket(mServerSock, FIONBIO, &nbio);#else fcntl(mServerSock, F_SETFL, O_NONBLOCK);#endif setsockopt(mServerSock, SOL_SOCKET, SO_REUSEADDR, (const char*)&bReuseaddr, sizeof(bReuseaddr)); struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(mPort); server_addr.sin_addr.s_addr = INADDR_ANY; if (bind(mServerSock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { LogMsg("bind failed!"); goto failed; } if (listen(mServerSock, MAX_CONN) == -1) { LogMsg("listen failed!"); goto failed; } WBTRACE("Listening port %d ...\n", mPort); mFailed = 0; return 0;failed: WBTRACE("CreateServerSocket failed!");#ifdef WIN32 closesocket(mServerSock);#else close(mServerSock);#endif return -1;}int MsgServer::Send(const char *pData){ if (strlen(pData) + strlen(mSendBuffer) < BUFFER_SIZE) { strcat(mSendBuffer, pData); return 0; } else { //buffer overflow return -1; }}int MsgServer::AddTrigger(int instance, int msg, int *trigger){ for (int i = 0; i < MAX_TRIGGER; i++) { if (mTriggers[i].mInstance == EMPTY_TRIGGER) { mTriggers[i].mInstance = instance; mTriggers[i].mMsg = msg; mTriggers[i].mTrigger = trigger; return 0; } } //no more room return -1;}int MsgServer::Listen(){ if (mFailed) return -1; mCounter++; int ret = 0; if (mCounter >= 200 && mMsgSock < 0) { // haven't received any connection request after 200 times. quit return -1; } FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds);#ifdef WIN32 // Type cast to avoid warning message: // warning C4018: '==' : signed/unsigned mismatch FD_SET((UINT32)mServerSock, &readfds); FD_SET((UINT32)mServerSock, &writefds); FD_SET((UINT32)mServerSock, &exceptfds);#else FD_SET(mServerSock, &readfds); FD_SET(mServerSock, &writefds); FD_SET(mServerSock, &exceptfds);#endif // the value of the highest file descriptor plus one. int maxfdp1 = mServerSock + 1; if (mMsgSock >= 0) {#ifdef WIN32 // Type cast to avoid warning message: // warning C4018: '==' : signed/unsigned mismatch FD_SET((UINT32)mMsgSock, &readfds); FD_SET((UINT32)mMsgSock, &writefds); FD_SET((UINT32)mMsgSock, &exceptfds); #else FD_SET(mMsgSock, &readfds); FD_SET(mMsgSock, &writefds); FD_SET(mMsgSock, &exceptfds); #endif maxfdp1 = mMsgSock + 1; } // wait for 1 second if no connect or recv/send socket requests. struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; int n = select(maxfdp1, &readfds, &writefds, &exceptfds, &tv); if (n < 0) { WBTRACE("Exception occurred!\n"); ret = -1; } else if (n > 0) { if (FD_ISSET(mServerSock, &readfds)) { struct sockaddr_in peer_addr; int len = sizeof(peer_addr);#ifdef WIN32 if ((mMsgSock = accept(mServerSock, (struct sockaddr*)&peer_addr, &len)) == -1) {#else if ((mMsgSock = accept(mServerSock, (struct sockaddr*)&peer_addr, (socklen_t*)&len)) == -1) {#endif WBTRACE("accept fail!\n"); ret = -1; } } else if (FD_ISSET(mServerSock, &exceptfds)) { WBTRACE("Exception occurred!\n"); ret = -1; } else if (FD_ISSET(mMsgSock, &readfds)) { ret = RecvData(); } else if (FD_ISSET(mMsgSock, &writefds)) { ret = SendData(); } else if (FD_ISSET(mMsgSock, &exceptfds)) { WBTRACE("Exception occurred!\n"); ret = -1; } } return ret;}int MsgServer::RecvData(){ char buf[BUFFER_SIZE] = "\0"; char unfinishedMsgBuf[BUFFER_SIZE] = "\0"; int len = recv(mMsgSock, buf, BUFFER_SIZE, 0); if (len == 0) { // value 0 means the network connection is closed. WBTRACE("client socket has been closed!\n"); return -1; } else if (len < 0) { // value -1 indicates a failure WBTRACE("receive fail!\n"); return len; } buf[len] = 0; WBTRACE("Client socket recv %s\n", buf); if (len + strlen(mRecvBuffer) < BUFFER_SIZE) { strcat(mRecvBuffer, buf); memset(buf, '\0', strlen(buf)); } char *delimiterPtr = strstr(mRecvBuffer, MSG_DELIMITER); if (!delimiterPtr) { // The message buffer has no message delimiters, should be part // of a long ( > BUFFER_SIZE) message. Cache the message piece // into the long message buffer (mLongRecvBuffer). if (len + (int)strlen(mLongRecvBuffer) >= mLongRecvBufferSize) { char *tmpRecvBuffer = mLongRecvBuffer; mLongRecvBufferSize += BUFFER_SIZE * 4; mLongRecvBuffer = new char [mLongRecvBufferSize]; memset(mLongRecvBuffer, '\0', mLongRecvBufferSize); strcpy(mLongRecvBuffer, tmpRecvBuffer); delete [] tmpRecvBuffer; } strcat(mLongRecvBuffer, mRecvBuffer); // Clear the normal message buffer for incoming new messages. memset(mRecvBuffer, '\0', strlen(mRecvBuffer)); } else { // find the last message delimiter, the left characters are part // of an unfinished message. char *tmpPtr; while (tmpPtr = strstr(delimiterPtr + strlen(MSG_DELIMITER), \ MSG_DELIMITER)) delimiterPtr = tmpPtr; for (int i = 0; i < (int)strlen(MSG_DELIMITER); i++) *(delimiterPtr + i) = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -