Client Struct: //===============Client Struct================ #pragma pack(push,4) #define LOG_SEND 0 #define MSG_SEND 1 #define EXIT_SEND 2 #define BUFFER_MAX_SIZE 512 #define HEADER_LEN sizeof(Header) typedef struct HeaderStruct { int OP;//OP : 0--> Login 1--> SendMsg 2--> Exit int size; }Header; //#define LOG_INFO_TIME_OFFSET (sizeof(Log) - 2 * sizeof(char *)) #define LOG_INFO_TIME_OFFSET (sizeof(Log) - 2 * sizeof(int))//Modify 2009年7月15日15:15:14 #define LOG_INFO_USERNAME_OFFSET(pLog) (LOG_INFO_TIME_OFFSET + pLog->timeLen* 2 ) typedef struct LogStruct { int timeLen; int userNameLen; char* time; char* userName; }Log; //#define SENDMSG_INFO_USERNAME_OFFSET (sizeof(SendMsg) - 3 * sizeof(char *)) #define SENDMSG_INFO_USERNAME_OFFSET (sizeof(SendMsg) - 3 * sizeof(int)) #define SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg) (SENDMSG_INFO_USERNAME_OFFSET + pSendMsg->userNameLen * 2) #define SENDMSG_INFO_TIME_OFFSET(pSendMsg) (SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg) + pSendMsg->sendMsgLen * 2) typedef struct SendMsgStruct { int userNameLen; int sendMsgLen; int timeLen; char* userName; char* sendMsg; char* time; }SendMsg; #pragma pack(pop) #include <stdio.h> #include <iostream> #include <process.h> #include <time.h> #include <string.h> #include "winsock2.h" #include "SendStruct.h" unsigned __stdcall SendThread(void* socket); //Unicode转换为Ascii void uni2str(const LPWSTR wstr, char *str) { int len; len = wcslen(wstr); if(len == 0 ){ str[0] = 0; return; } memset(str,0,(len+1)*2); WideCharToMultiByte(CP_ACP,0,(LPWSTR)wstr,len,str,(len*2 + 1),NULL, NULL); } //Ascii转换为Unicode void str2uni(const char *str, LPWSTR wstr) { int len; len = strlen(str); if(len == 0 ){ wstr[0] = 0; return ; } memset((char*)wstr,0,(len+1)*2); MultiByteToWideChar(CP_ACP,0,str,len, wstr,(len+1) * 2); } //Unicode主机序转换为网络序 void unih2n(LPWSTR uniStr) { for(; *uniStr != 0; uniStr++){ *uniStr = htons((short)*uniStr); } } //Unicode网络序转换为主机序 void unin2h(LPWSTR uniStr) { int i; int len ; len = wcslen((wchar_t*)uniStr); for(i=0;i<len;i++) uniStr[i] = ntohs((short)uniStr[i]); } //构建数据函数 retCmdId根据Header中的OP来的。把数据构建到buffer(包含头信息和数据信息)中 int constructDataBuff(int retCmdId,char *buff) { Header* pCmdHeader; Log* pLog; SendMsg* pSendMsg; int dataLen = 0; char* tmpBuf; LPWSTR uniStr; pCmdHeader = (Header *)buff; pCmdHeader->OP = htonl(retCmdId); pCmdHeader->size = htonl(pCmdHeader->size); tmpBuf = buff + HEADER_LEN; if(retCmdId == LOG_SEND)//Send Log Info { pLog = (Log *)tmpBuf; //======================================== pLog->timeLen = htonl(pLog->timeLen); pLog->userNameLen = htonl(pLog->userNameLen); //======================================== uniStr = (LPWSTR)(tmpBuf + LOG_INFO_TIME_OFFSET); str2uni(pLog->time,uniStr); unih2n(uniStr); dataLen += pLog->timeLen ; uniStr = (LPWSTR)(tmpBuf + LOG_INFO_USERNAME_OFFSET(pLog)); str2uni(pLog->userName,uniStr); unih2n(uniStr); dataLen += pLog->userNameLen; } else if(retCmdId == MSG_SEND)//Send Msg Info { pSendMsg = (SendMsg *)tmpBuf; //======================================== pSendMsg->userNameLen = htonl(pSendMsg->userNameLen); pSendMsg->sendMsgLen = htonl(pSendMsg->sendMsgLen); pSendMsg->timeLen = htonl(pSendMsg->timeLen); //======================================== uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_USERNAME_OFFSET); str2uni(pSendMsg->userName,uniStr); unih2n(uniStr); dataLen += pSendMsg->userNameLen * 2; uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg)); str2uni(pSendMsg->sendMsg,uniStr); unih2n(uniStr); dataLen += pSendMsg->sendMsgLen * 2; uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_TIME_OFFSET(pSendMsg)); str2uni(pSendMsg->time,uniStr); unih2n(uniStr); dataLen += pSendMsg->timeLen * 2; } pCmdHeader->size = htonl(dataLen); dataLen += HEADER_LEN; return dataLen; } //构建数据函数 retCmdId根据Header中的OP来的。把现有数据构建到buffer(包含头信息和数据信息)中 int constructDataBuffBySource(int retCmdId,char *buff,char *buffSource) { Header* pCmdHeader; Log* pLog; SendMsg* pSendMsg; int dataLen = 0; char* tmpBuf; LPWSTR uniStr; char tmp[512]; LPWSTR tmpUniStr; wchar_t uniChar; pCmdHeader = (Header *)buff; pCmdHeader->OP = htonl(retCmdId); tmpBuf = buff + HEADER_LEN; if(retCmdId == LOG_SEND)//Send Log Info { pLog = (Log *)tmpBuf; //将buffSource转换为Log结构 Log * pTmpLog = (Log *)(buffSource); //======================================== pLog->timeLen = htonl(pTmpLog->timeLen); pLog->userNameLen = htonl(pTmpLog->userNameLen); //======================================== dataLen = LOG_INFO_TIME_OFFSET; //找到buffSource对应time的OFFSET。 tmpUniStr = (LPWSTR)(buffSource + LOG_INFO_TIME_OFFSET); uniChar = tmpUniStr[pTmpLog->timeLen]; tmpUniStr[pTmpLog->timeLen] = 0; //将tmpUniStr里的值转换成本地 unin2h(tmpUniStr); //将Unicode转换为Ascii。并赋值给tmp数组 uni2str(tmpUniStr,tmp); tmpUniStr[pTmpLog->timeLen] = uniChar; uniStr = (LPWSTR)(tmpBuf + LOG_INFO_TIME_OFFSET); str2uni(tmp,uniStr); unih2n(uniStr); dataLen += pLog->timeLen * 2; tmpUniStr = (LPWSTR)(buffSource + LOG_INFO_USERNAME_OFFSET(pTmpLog) ); tmpUniStr[pTmpLog->userNameLen] = 0; //将tmpUniStr里的值转换成本地 unin2h(tmpUniStr); //将Unicode转换为Ascii。并赋值给tmp数组 uni2str(tmpUniStr,tmp); uniStr = (LPWSTR)(tmpBuf + LOG_INFO_USERNAME_OFFSET(pLog)); str2uni(tmp,uniStr); unih2n(uniStr); dataLen += pLog->userNameLen * 2; } else if(retCmdId == MSG_SEND)//Send Msg Info { pSendMsg = (SendMsg *)tmpBuf; SendMsg * pTmpSendMsg = (SendMsg *)(buffSource); //======================================== pSendMsg->userNameLen = htonl(pTmpSendMsg->userNameLen); pSendMsg->sendMsgLen = htonl(pTmpSendMsg->sendMsgLen); pSendMsg->timeLen = htonl(pTmpSendMsg->timeLen); //======================================== dataLen = SENDMSG_INFO_USERNAME_OFFSET; //找到buffSource对应userName的OFFSET。 tmpUniStr = (LPWSTR)(buffSource + SENDMSG_INFO_USERNAME_OFFSET); uniChar = tmpUniStr[pTmpSendMsg->userNameLen]; tmpUniStr[pTmpSendMsg->userNameLen] = 0; //将tmpUniStr里的值转换成本地 unin2h(tmpUniStr); //将Unicode转换为Ascii。并赋值给tmp数组 uni2str(tmpUniStr,tmp); tmpUniStr[pTmpSendMsg->userNameLen] = uniChar; uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_USERNAME_OFFSET); str2uni(tmp,uniStr); unih2n(uniStr); dataLen += pSendMsg->userNameLen * 2; //找到buffSource对应sendMsg的OFFSET。 tmpUniStr = (LPWSTR)(buffSource + SENDMSG_INFO_SENDMSG_OFFSET(pTmpSendMsg)); uniChar = tmpUniStr[pTmpSendMsg->userNameLen]; tmpUniStr[pTmpSendMsg->userNameLen] = 0; //将tmpUniStr里的值转换成本地 unin2h(tmpUniStr); //将Unicode转换为Ascii。并赋值给tmp数组 uni2str(tmpUniStr,tmp); tmpUniStr[pTmpSendMsg->userNameLen] = uniChar; uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg)); str2uni(tmp,uniStr); unih2n(uniStr); dataLen += pSendMsg->sendMsgLen * 2; //找到buffSource对应time的OFFSET。 tmpUniStr = (LPWSTR)(buffSource + SENDMSG_INFO_TIME_OFFSET(pTmpSendMsg)); tmpUniStr[pTmpSendMsg->userNameLen] = 0; //将tmpUniStr里的值转换成本地 unin2h(tmpUniStr); //将Unicode转换为Ascii。并赋值给tmp数组 uni2str(tmpUniStr,tmp); uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_TIME_OFFSET(pSendMsg)); str2uni(tmp,uniStr); unih2n(uniStr); dataLen += pSendMsg->timeLen * 2; } pCmdHeader->size = htonl(dataLen); dataLen += HEADER_LEN; return dataLen; } int constructDataBuffByLog(char *buff, Log * logBuffSource) { Header* pCmdHeader; Log* pLog; int dataLen = 0; char* tmpBuf; LPWSTR uniStr; //int tmpLenTime,tmpLenName; pCmdHeader = (Header *)buff; pCmdHeader->OP = htonl(0); tmpBuf = buff + HEADER_LEN; pLog = (Log *)tmpBuf; pLog->timeLen = logBuffSource->timeLen; pLog->userNameLen = logBuffSource->userNameLen; dataLen = LOG_INFO_TIME_OFFSET; uniStr = (LPWSTR)(tmpBuf + LOG_INFO_TIME_OFFSET); str2uni(logBuffSource->time,uniStr); unih2n(uniStr); dataLen += pLog->timeLen * 2; int len = LOG_INFO_USERNAME_OFFSET(pLog); uniStr = (LPWSTR)(tmpBuf + LOG_INFO_USERNAME_OFFSET(pLog)); str2uni(logBuffSource->userName,uniStr); unih2n(uniStr); dataLen += pLog->userNameLen * 2; pLog->timeLen = htonl(pLog->timeLen); pLog->userNameLen = htonl(pLog->userNameLen); pCmdHeader->size = htonl(dataLen); dataLen += HEADER_LEN; return dataLen; } int constructDataBuffBySendMsg(char *buff,SendMsg * sendMsgSource) { Header* pCmdHeader; SendMsg* pSendMsg; int dataLen = 0; char* tmpBuf; LPWSTR uniStr; pCmdHeader = (Header *)buff; pCmdHeader->OP = htonl(1); tmpBuf = buff + HEADER_LEN; pSendMsg = (SendMsg *)tmpBuf; pSendMsg->userNameLen = sendMsgSource->userNameLen; pSendMsg->sendMsgLen = sendMsgSource->sendMsgLen; pSendMsg->timeLen = sendMsgSource->timeLen; dataLen = SENDMSG_INFO_USERNAME_OFFSET; uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_USERNAME_OFFSET); printf("in constructDataBuffBySendMsg --- the sendMsgSource->userName is %s/n",sendMsgSource->userName); str2uni(sendMsgSource->userName, uniStr); unih2n(uniStr); dataLen += pSendMsg->userNameLen * 2; uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg)); //=======error======= int len = SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg); printf("%s",sendMsgSource->sendMsg); str2uni(sendMsgSource->sendMsg,uniStr); unih2n(uniStr); dataLen += pSendMsg->sendMsgLen * 2; uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_TIME_OFFSET(pSendMsg)); str2uni(sendMsgSource->time,uniStr); unih2n(uniStr); dataLen += pSendMsg->timeLen * 2; pSendMsg->userNameLen = htonl(pSendMsg->userNameLen); pSendMsg->sendMsgLen = htonl(pSendMsg->sendMsgLen); pSendMsg->timeLen = htonl(pSendMsg->timeLen); pCmdHeader->size = htonl(dataLen); dataLen += HEADER_LEN; return dataLen; } //转换所接收数据,并打印输出,不包含头信息 void convertDataAndPrint(int cmdId,char *buff, unsigned int dataLen) { Log *pLog; SendMsg *pSendMsg; char tmp[512]; //char * tmpBuf; LPWSTR uniStr; wchar_t uniChar; //int i; unsigned int len; printf("/n=====================================================/n"); if(cmdId == LOG_SEND) { pLog = (Log *)(buff); pLog->timeLen = ntohl(pLog->timeLen); pLog->userNameLen = ntohl(pLog->userNameLen); len =LOG_INFO_TIME_OFFSET + pLog->timeLen * 2; if(len > dataLen) { printf("错误:数据解析越界,时间长度无效(%d)/n", pLog->timeLen); return; } //time uniStr = (LPWSTR)(buff + LOG_INFO_TIME_OFFSET); //这里是把uniStr所切取的字符串最后一位字符给uniChar(因为该位上可能是下一个数据的值)。 //再让uniStr最后一位为0,成为一个字符串。最后将uniChar里的值还回去 uniChar = uniStr[pLog->timeLen]; //the end is '/0' uniStr[pLog->timeLen] = 0; //Unicode network order Trans To Host order unin2h(uniStr); //Unicode Trans To AscII,tmp is char(single char) uni2str(uniStr,tmp); uniStr[pLog->timeLen] = uniChar; printf("[%s]: ",tmp); len += pLog->userNameLen * 2; if(len > dataLen) { printf("错误:数据解析越界,姓名长度无效(%d)/n", pLog->userNameLen); return; } //userName uniStr = (LPWSTR)(buff + LOG_INFO_USERNAME_OFFSET(pLog)); //uniChar = uniStr[pLog->userNameLen]; uniStr[pLog->userNameLen] = 0; unin2h(uniStr); uni2str(uniStr,tmp); //uniStr[pLog->userNameLen] = uniChar; printf("%s connected.../n",tmp); printf("=====================LogInfo End=======================/n"); } else if(cmdId == MSG_SEND) { pSendMsg = (SendMsg *)buff; pSendMsg->userNameLen = ntohl(pSendMsg->userNameLen); pSendMsg->sendMsgLen = ntohl(pSendMsg->sendMsgLen); pSendMsg->timeLen = ntohl(pSendMsg->timeLen); len = SENDMSG_INFO_USERNAME_OFFSET + pSendMsg->userNameLen * 2; if(len > dataLen) { printf("错误:数据解析越界,姓名长度无效(%d)/n", pSendMsg->userNameLen); return; } //userName uniStr = (LPWSTR)(buff + SENDMSG_INFO_USERNAME_OFFSET); uniChar = uniStr[pSendMsg->userNameLen]; uniStr[pSendMsg->userNameLen] = 0; unin2h(uniStr); uni2str(uniStr,tmp); uniStr[pSendMsg->userNameLen] = uniChar; printf("[%s] ",tmp); len += pSendMsg->sendMsgLen * 2; if(len > dataLen) { printf("错误:数据解析越界,信息长度无效(%d)/n",pSendMsg->sendMsgLen); return; } //sendMsg long len2 =SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg); len2 = ntohl(len2); uniStr = (LPWSTR)(buff + SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg)); //long len2 =SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg); uniChar = uniStr[pSendMsg->sendMsgLen]; uniStr[pSendMsg->sendMsgLen] = 0; unin2h(uniStr); uni2str(uniStr,tmp); uniStr[pSendMsg->sendMsgLen] = uniChar; printf(" %s ",tmp); len += pSendMsg->timeLen * 2; if(len > dataLen) { printf("错误:数据解析越界,时间长度无效(%d)/n",pSendMsg->timeLen); return; } //time uniStr = (LPWSTR) (buff + SENDMSG_INFO_TIME_OFFSET(pSendMsg)); uniStr[pSendMsg->timeLen] = 0; unin2h(uniStr); uni2str(uniStr,tmp); printf(" [%s] /n",tmp); printf("====================SendMsgInfo End====================/n"); } } void main() { // 检查 Winsock 版本号,WSAData为WSADATA结构对象 WSADATA wsaData; int iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != NO_ERROR) printf("Error at WSAStartup()/n"); //创建套接字 SOCKET ConnectSocket; ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (ConnectSocket == INVALID_SOCKET) { printf("Error at socket(): %ld/n", WSAGetLastError()); WSACleanup(); return; } //填写远程地址信息 sockaddr_in clientService; clientService.sin_family = AF_INET; clientService.sin_port = htons( 27015 ); //填写服务器程序所在的机器的IP地址 clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" ); //连接服务器端 if ( connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR) { printf( "Failed to connect./n" ); WSACleanup(); return; } //创建句柄 HANDLE hCliThread; unsigned threadID; //产生线程 3.线程创建后调用的函数,4.该函数的参数,6.线程ID 方便对线程进行管理 hCliThread = (HANDLE)_beginthreadex(NULL,0,SendThread,(void *)ConnectSocket,0,&threadID); int bytesRecv = 0; //创建一个接收的结构体,用于接收并解析 Header *recvHeader = (Header *)malloc(HEADER_LEN); char* buffer; buffer = (char *)malloc(BUFFER_MAX_SIZE); for(;;)//recevice data from server { //接收连接上来的服务端,在客户器端创建一个socket为ConnectSocket bytesRecv = recv(ConnectSocket,(char *)recvHeader,HEADER_LEN,0); if(bytesRecv <= 0 || bytesRecv == WSAECONNRESET) { printf("client didn't recv data from server,then disconnect with server, %d/n", WSAGetLastError()); break; } recvHeader->OP = ntohl(recvHeader->OP); recvHeader->size = ntohl(recvHeader->size); printf("recv HeaderInfo: OP: %d ,size : %d /n",recvHeader->OP,recvHeader->size); if(recvHeader->size > 0 && recvHeader->size < BUFFER_MAX_SIZE) { bytesRecv = recv(ConnectSocket,buffer,recvHeader->size,0); if(bytesRecv <= 0 || bytesRecv == WSAECONNRESET) { printf("client disconnect with server(%d)",WSAGetLastError()); break; } //打印数据信息 convertDataAndPrint(recvHeader->OP,buffer,recvHeader->size); } } free(buffer); WSACleanup(); return; } unsigned __stdcall SendThread(void *socket)//send data to otherclient and server { Header header; SendMsg sendMsg; Log log; int dataLen; char *buffer; char pUserName[40]; char pSendMsg[512]; //int userNameLen; char time[8] = "2009"; buffer = (char *)malloc(BUFFER_MAX_SIZE); printf("======Welcome to YY ChatRoom======/n"); printf("========Log========:/n"); //==================登录 并发送登录信息================= printf("Your Name : "); scanf("%s",pUserName); printf("your name is: %s/n",pUserName); log.userName = pUserName; log.userNameLen = strlen(log.userName); //_strtime(time); log.time = time; log.timeLen = strlen(log.time); header.OP = 0; dataLen = constructDataBuffByLog(buffer,&log); int sendLen = send((SOCKET)socket,buffer,dataLen,0); printf("the DataLen is : %d the SendLen is %d/n",dataLen,sendLen); if (sendLen < 0) { printf("Client: disconnect with server,(%d)", WSAGetLastError()); return 0; } memset(buffer,0,BUFFER_MAX_SIZE); //==================登录 并发送登录信息 结束================= //循环发送数据信息给server端 while(1) { sendMsg.userName = pUserName; sendMsg.userNameLen =strlen(pUserName); printf("Input:"); scanf("%s",pSendMsg); sendMsg.sendMsg = pSendMsg; sendMsg.sendMsgLen = strlen(sendMsg.sendMsg); //_strtime(time); sendMsg.time = time; sendMsg.timeLen = strlen(sendMsg.time); header.OP = htonl(1); //header.size = htonl(sendMsg.userNameLen + sendMsg.sendMsgLen + sendMsg.timeLen); dataLen = constructDataBuffBySendMsg(buffer,&sendMsg); int sendLen = send((SOCKET)socket,buffer,dataLen,0); if(sendLen < 0) { printf("Client: disconnect with server/n"); break; } printf("the dataLen is (%d),the sendLen is(%d)/n",dataLen,sendLen); memset(buffer,0,BUFFER_MAX_SIZE); } //结束线程 free(buffer); _endthreadex( 0 ); return 0; } Server Struct: //=============Server Struct=============== #pragma pack(push,4) #define LOG_SEND 0 #define MSG_SEND 1 #define EXIT_SEND 2 #define BUFFER_MAX_SIZE 512 #define HEADER_LEN sizeof(Header) typedef struct HeaderStruct { int OP;//OP : 0--> Login 1--> SendMsg 2--> Exit int size; }Header; //#define LOG_INFO_TIME_OFFSET (sizeof(Log) - 2 * sizeof(char *)) #define LOG_INFO_TIME_OFFSET (sizeof(Log) - 2 * sizeof(int)) #define LOG_INFO_USERNAME_OFFSET(pLog) (LOG_INFO_TIME_OFFSET + pLog->timeLen * 2 ) typedef struct LogStruct { int timeLen; int userNameLen; char* time; char* userName; }Log; // //#define SENDMSG_INFO_USERNAME_OFFSET (sizeof(SendMsg) - 3 * sizeof(char *)) #define SENDMSG_INFO_USERNAME_OFFSET (sizeof(SendMsg) - 3 * sizeof(int)) #define SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg) (SENDMSG_INFO_USERNAME_OFFSET + pSendMsg->userNameLen * 2) #define SENDMSG_INFO_TIME_OFFSET(pSendMsg) (SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg) + pSendMsg->sendMsgLen * 2) typedef struct SendMsgStruct { int userNameLen; int sendMsgLen; int timeLen; char* userName; char* sendMsg; char* time; }SendMsg; #pragma pack(pop) #define BACKLOG (int)20 /* 多少等待连接控制*/ #include <stdio.h> #include <process.h> #include "winsock2.h" #include <time.h> #include "SendStruct.h" unsigned __stdcall SockThread(void *socket); //CRITICALSECTION CriticalSection;//define critical resource SOCKET socketArr[BACKLOG];//save socket from client HOSTENT *host; //struct MsgStruct clientNameStr[BACKLOG];//save recv name from client static int socketLen = 0; sockaddr_in remoteAddr;//接受的socket //Unicode转换为AscII void uni2str(const LPWSTR wstr,char *str) { int len; len = wcslen(wstr); if(len == 0) { str[0] = 0; return; } memset(str,0,(len + 1) * 2); WideCharToMultiByte(CP_ACP,0,(LPWSTR)wstr,len,str,(len * 2 + 1),NULL,NULL); } //AscII转换为Unicode void str2uni(const char *str,LPWSTR wstr) { int len; len = strlen(str); if(len == 0) { wstr[0] = 0; return; } memset((char *)wstr,0,(len + 1) * 2); MultiByteToWideChar(CP_ACP,0,str,len,wstr,(len + 1) * 2); } //Unicode主机序转换为网络序 void unih2n(LPWSTR uniStr) { for(; *uniStr != 0;uniStr++) { *uniStr = htons((short)*uniStr); } } //Unicode网络序转换为主机序 void unin2h(LPWSTR uniStr) { int i; int len; len = wcslen((wchar_t*)uniStr); for(i = 0;i < len;i++) { uniStr[i] = ntohs((short)uniStr[i]); } } //构建数据函数 retCmdId根据Header中的OP来的。把数据构建到buffer(包含头信息和数据信息)中 int constructDataBuff(int retCmdId,char *buff) { //Header* pCmdHeader = (Header *)malloc(HEADER_LEN); Log* pLog; SendMsg* pSendMsg; int dataLen = 0; char* tmpBuf; LPWSTR uniStr; //pCmdHeader = (Header *)buff; //pCmdHeader->OP = htonl(retCmdId); //pCmdHeader->size = htonl(pCmdHeader->size); //tmpBuf = buff + HEADER_LEN; tmpBuf = buff; if(retCmdId == LOG_SEND)//Send Log Info { pLog = (Log *)tmpBuf; //======================================== //======================================== uniStr = (LPWSTR)(tmpBuf + LOG_INFO_TIME_OFFSET); str2uni(pLog->time,uniStr); unih2n(uniStr); dataLen += pLog->timeLen ; uniStr = (LPWSTR)(tmpBuf + LOG_INFO_USERNAME_OFFSET(pLog)); str2uni(pLog->userName,uniStr); unih2n(uniStr); dataLen += pLog->userNameLen; pLog->timeLen = htonl(pLog->timeLen); pLog->userNameLen = htonl(pLog->userNameLen); } else if(retCmdId == MSG_SEND)//Send Msg Info { pSendMsg = (SendMsg *)tmpBuf; //======================================== //pSendMsg->userNameLen = pSendMsg->userNameLen; //pSendMsg->sendMsgLen =pSendMsg->sendMsgLen; //pSendMsg->timeLen = pSendMsg->timeLen; //======================================== uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_USERNAME_OFFSET); str2uni(pSendMsg->userName,uniStr); unih2n(uniStr); dataLen += pSendMsg->userNameLen * 2; uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg)); int tmpLen = SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg); //tmpLen = pSendMsg->sendMsgLen; str2uni(pSendMsg->sendMsg,uniStr); unih2n(uniStr); dataLen += pSendMsg->sendMsgLen * 2; uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_TIME_OFFSET(pSendMsg)); tmpLen = SENDMSG_INFO_TIME_OFFSET(pSendMsg); tmpLen = pSendMsg->timeLen; str2uni(pSendMsg->time,uniStr); unih2n(uniStr); dataLen += pSendMsg->timeLen * 2; pSendMsg->userNameLen = htonl(pSendMsg->userNameLen); pSendMsg->sendMsgLen = htonl(pSendMsg->sendMsgLen); pSendMsg->timeLen = htonl(pSendMsg->timeLen); } //pCmdHeader->size = htonl(dataLen); dataLen += HEADER_LEN; return dataLen; } //构建数据函数 retCmdId根据Header中的OP来的。把现有数据构建到buffer(包含头信息和数据信息)中 int constructDataBuffBySource(int retCmdId,char *buff,char *buffSource) { Header* pCmdHeader; Log* pLog; SendMsg* pSendMsg; int dataLen = 0; char* tmpBuf; LPWSTR uniStr; char tmp[512]; LPWSTR tmpUniStr; wchar_t uniChar; pCmdHeader = (Header *)buff; pCmdHeader->OP = htonl(retCmdId); tmpBuf = buff + HEADER_LEN; if(retCmdId == LOG_SEND)//Send Log Info { pLog = (Log *)tmpBuf; //将buffSource转换为Log结构 Log * pTmpLog = (Log *)(buffSource); //======================================== pLog->timeLen = htonl(pTmpLog->timeLen); pLog->userNameLen = htonl(pTmpLog->userNameLen); //======================================== dataLen = LOG_INFO_TIME_OFFSET; //找到buffSource对应time的OFFSET。 tmpUniStr = (LPWSTR)(buffSource + LOG_INFO_TIME_OFFSET); uniChar = tmpUniStr[pTmpLog->timeLen]; tmpUniStr[pTmpLog->timeLen] = 0; //将tmpUniStr里的值转换成本地 //*****************unin2h(tmpUniStr); //将Unicode转换为Ascii。并赋值给tmp数组 uni2str(tmpUniStr,tmp); tmpUniStr[pTmpLog->timeLen] = uniChar; uniStr = (LPWSTR)(tmpBuf + LOG_INFO_TIME_OFFSET); str2uni(tmp,uniStr); unih2n(uniStr); dataLen += pLog->timeLen * 2; tmpUniStr = (LPWSTR)(buffSource + LOG_INFO_USERNAME_OFFSET(pTmpLog) ); tmpUniStr[pTmpLog->userNameLen] = 0; //将tmpUniStr里的值转换成本地 unin2h(tmpUniStr); //将Unicode转换为Ascii。并赋值给tmp数组 uni2str(tmpUniStr,tmp); uniStr = (LPWSTR)(tmpBuf + LOG_INFO_USERNAME_OFFSET(pLog)); str2uni(tmp,uniStr); unih2n(uniStr); dataLen += pLog->userNameLen * 2; } else if(retCmdId == MSG_SEND)//Send Msg Info { pSendMsg = (SendMsg *)tmpBuf; SendMsg * pTmpSendMsg = (SendMsg *)(buffSource); //======================================== pSendMsg->userNameLen = htonl(pTmpSendMsg->userNameLen); pSendMsg->sendMsgLen = htonl(pTmpSendMsg->sendMsgLen); pSendMsg->timeLen = htonl(pTmpSendMsg->timeLen); //======================================== dataLen = SENDMSG_INFO_USERNAME_OFFSET; //找到buffSource对应userName的OFFSET。 tmpUniStr = (LPWSTR)(buffSource + SENDMSG_INFO_USERNAME_OFFSET); uniChar = tmpUniStr[pTmpSendMsg->userNameLen]; tmpUniStr[pTmpSendMsg->userNameLen] = 0; //将tmpUniStr里的值转换成本地 unin2h(tmpUniStr); //将Unicode转换为Ascii。并赋值给tmp数组 uni2str(tmpUniStr,tmp); tmpUniStr[pTmpSendMsg->userNameLen] = uniChar; uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_USERNAME_OFFSET); str2uni(tmp,uniStr); unih2n(uniStr); dataLen += pSendMsg->userNameLen * 2; //找到buffSource对应sendMsg的OFFSET。 tmpUniStr = (LPWSTR)(buffSource + SENDMSG_INFO_SENDMSG_OFFSET(pTmpSendMsg)); uniChar = tmpUniStr[pTmpSendMsg->userNameLen]; tmpUniStr[pTmpSendMsg->userNameLen] = 0; //将tmpUniStr里的值转换成本地 unin2h(tmpUniStr); //将Unicode转换为Ascii。并赋值给tmp数组 uni2str(tmpUniStr,tmp); tmpUniStr[pTmpSendMsg->userNameLen] = uniChar; uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg)); str2uni(tmp,uniStr); unih2n(uniStr); dataLen += pSendMsg->sendMsgLen * 2; //找到buffSource对应time的OFFSET。 tmpUniStr = (LPWSTR)(buffSource + SENDMSG_INFO_TIME_OFFSET(pTmpSendMsg)); tmpUniStr[pTmpSendMsg->userNameLen] = 0; //将tmpUniStr里的值转换成本地 unin2h(tmpUniStr); //将Unicode转换为Ascii。并赋值给tmp数组 uni2str(tmpUniStr,tmp); uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_TIME_OFFSET(pSendMsg)); str2uni(tmp,uniStr); unih2n(uniStr); dataLen += pSendMsg->timeLen * 2; } pCmdHeader->size = htonl(dataLen); dataLen += HEADER_LEN; return dataLen; } int constructDataBuffByLog(char *buff, Log * logBuffSource) { Header* pCmdHeader; Log* pLog; int dataLen = 0; char* tmpBuf; LPWSTR uniStr; pCmdHeader = (Header *)buff; pCmdHeader->OP = htonl(0); tmpBuf = buff + HEADER_LEN; pLog = (Log *)tmpBuf; //======================================== pLog->timeLen = htonl(logBuffSource->timeLen); pLog->userNameLen = htonl(logBuffSource->userNameLen); //======================================== dataLen = LOG_INFO_TIME_OFFSET; uniStr = (LPWSTR)(tmpBuf + LOG_INFO_TIME_OFFSET); str2uni(logBuffSource->time,uniStr); unih2n(uniStr); dataLen += pLog->timeLen * 2; uniStr = (LPWSTR)(tmpBuf + LOG_INFO_USERNAME_OFFSET(pLog)); str2uni(logBuffSource->userName,uniStr); unih2n(uniStr); dataLen += pLog->userNameLen * 2; pCmdHeader->size = htonl(dataLen); dataLen += HEADER_LEN; return dataLen; } int constructDataBuffBySendMsg(char *buff,SendMsg * sendMsgSource) { Header* pCmdHeader; SendMsg* pSendMsg; int dataLen = 0; char* tmpBuf; LPWSTR uniStr; pCmdHeader = (Header *)buff; pCmdHeader->OP = htonl(1); tmpBuf = buff + HEADER_LEN; pSendMsg = (SendMsg *)tmpBuf; pSendMsg->userNameLen = sendMsgSource->userNameLen; pSendMsg->sendMsgLen = sendMsgSource->sendMsgLen; pSendMsg->timeLen = sendMsgSource->timeLen; dataLen = SENDMSG_INFO_USERNAME_OFFSET; uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_USERNAME_OFFSET); str2uni(sendMsgSource->userName,uniStr); unih2n(uniStr); dataLen += pSendMsg->userNameLen * 2; uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg)); //=======error======= int len = SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg); printf("%s",sendMsgSource->sendMsg); str2uni(sendMsgSource->sendMsg,uniStr); unih2n(uniStr); dataLen += pSendMsg->sendMsgLen * 2; uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_TIME_OFFSET(pSendMsg)); str2uni(sendMsgSource->time,uniStr); unih2n(uniStr); dataLen += pSendMsg->timeLen * 2; pSendMsg->userNameLen = htonl(pSendMsg->userNameLen); pSendMsg->sendMsgLen = htonl(pSendMsg->sendMsgLen); pSendMsg->timeLen = htonl(pSendMsg->timeLen); pCmdHeader->size = htonl(dataLen); dataLen += HEADER_LEN; return dataLen; } //转换所接收数据,并打印输出,不包含头信息 void convertDataAndPrint(int cmdId,char *buff, unsigned int dataLen) { Log *pLog; SendMsg *pSendMsg; char tmp[512]; LPWSTR uniStr; wchar_t uniChar; unsigned int len; printf("=====================================================/n"); if(cmdId == LOG_SEND) { pLog = (Log *)(buff); pLog->timeLen = ntohl(pLog->timeLen); pLog->userNameLen = ntohl(pLog->userNameLen); len =LOG_INFO_TIME_OFFSET + pLog->timeLen * 2; if(len > dataLen) { printf("错误:数据解析越界,时间长度无效(%d)/n", pLog->timeLen); return; } //time uniStr = (LPWSTR)(buff + LOG_INFO_TIME_OFFSET); //这里是把uniStr所切取的字符串最后一位字符给uniChar(因为该位上可能是下一个数据的值)。 //再让uniStr最后一位为0,成为一个字符串。最后将uniChar里的值还回去 uniChar = uniStr[pLog->timeLen]; //the end is '/0' uniStr[pLog->timeLen] = 0; //Unicode network order Trans To Host order unin2h(uniStr); //Unicode Trans To AscII,tmp is char(single char) uni2str(uniStr,tmp); uniStr[pLog->timeLen] = uniChar; printf("[%s]: ",tmp); len += pLog->userNameLen * 2; if(len > dataLen) { printf("错误:数据解析越界,姓名长度无效(%d)/n", pLog->userNameLen); return; } //userName uniStr = (LPWSTR)(buff + LOG_INFO_USERNAME_OFFSET(pLog)); uniChar = uniStr[pLog->userNameLen]; uniStr[pLog->userNameLen] = 0; unin2h(uniStr); uni2str(uniStr,tmp); uniStr[pLog->userNameLen] = uniChar; printf("%s connected.../n",tmp); printf("=====================LogInfo End=======================/n"); } else if(cmdId == MSG_SEND) { pSendMsg = (SendMsg *)buff; pSendMsg->userNameLen = ntohl(pSendMsg->userNameLen); pSendMsg->sendMsgLen = ntohl(pSendMsg->sendMsgLen); pSendMsg->timeLen = ntohl(pSendMsg->timeLen); len = SENDMSG_INFO_USERNAME_OFFSET + pSendMsg->userNameLen * 2; if(len > dataLen) { printf("错误:数据解析越界,姓名长度无效(%d)/n", pSendMsg->userNameLen); return; } //userName uniStr = (LPWSTR)(buff + SENDMSG_INFO_USERNAME_OFFSET); uniChar = uniStr[pSendMsg->userNameLen]; uniStr[pSendMsg->userNameLen] = 0; unin2h(uniStr); uni2str(uniStr,tmp); uniStr[pSendMsg->userNameLen] = uniChar; printf("[%s] ",tmp); len += pSendMsg->sendMsgLen * 2; if(len > dataLen) { printf("错误:数据解析越界,信息长度无效(%d)/n",pSendMsg->sendMsgLen); return; } //sendMsg uniStr = (LPWSTR)(buff + SENDMSG_INFO_SENDMSG_OFFSET(pSendMsg)); uniChar = uniStr[pSendMsg->sendMsgLen]; uniStr[pSendMsg->sendMsgLen] = 0; unin2h(uniStr); uni2str(uniStr,tmp); uniStr[pSendMsg->sendMsgLen] = uniChar; printf(" %s ",tmp); len += pSendMsg->timeLen * 2; if(len > dataLen) { printf("错误:数据解析越界,时间长度无效(%d)/n",pSendMsg->timeLen); return; } //time uniStr = (LPWSTR) (buff + SENDMSG_INFO_TIME_OFFSET(pSendMsg)); uniChar = uniStr[pSendMsg->sendMsgLen]; uniStr[pSendMsg->timeLen] = 0; unin2h(uniStr); uni2str(uniStr,tmp); uniStr[pSendMsg->sendMsgLen] = uniChar; printf(" [%s]/n",tmp); printf("====================SendMsgInfo End====================/n"); } } void main() { //INITIALIZECRITICALSECTION CriticalSection; int nAddrLen = sizeof(remoteAddr); SOCKET sClient; memset(&socketArr,0,sizeof(socketLen)); // 检查 Winsock 版本号,WSAData为WSADATA结构对象 WSADATA wsaData; int iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != NO_ERROR) { printf("Error at WSAStartup()/n"); return; } //创建套接字 SOCKET ListenSocket; ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (ListenSocket == INVALID_SOCKET) { printf("Error at socket(): %ld/n", WSAGetLastError()); WSACleanup(); return; } //填充sockaddr_in结构 sockaddr_in service; service.sin_family = AF_INET; service.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); service.sin_port = htons(27015); //绑定这个套接字到一个本地地址 if (bind( ListenSocket,(SOCKADDR*)&service,sizeof(service)) == SOCKET_ERROR) { printf("bind() failed./n"); closesocket(ListenSocket); WSACleanup(); return; } // 进入监听模式 if (listen( ListenSocket, BACKLOG ) == SOCKET_ERROR) { printf("Error listening on socket./n"); closesocket(ListenSocket); WSACleanup(); return ; } printf("listening...../n"); while(true) { //循环接收连接上来的客户端 sClient = accept(ListenSocket,(SOCKADDR*)&remoteAddr,&nAddrLen); if(sClient == INVALID_SOCKET) { printf("Failed accept!/n"); continue; } //else //{ // int bytesRecv = 0; // //创建一个接收的结构体,用于接收并解析 // Header *recvHeader = (Header *)malloc(HEADER_LEN); // char* buffer; // buffer = (char *)malloc(BUFFER_MAX_SIZE); // bytesRecv = recv(sClient,(char *)recvHeader,HEADER_LEN,0); // if(bytesRecv <= 0 || bytesRecv == WSAECONNRESET) // { // printf("server didn't recv data from client,then disconnect with server, %d/n", WSAGetLastError()); // break; // } // // recvHeader->OP = ntohl(recvHeader->OP); // recvHeader->size = ntohl(recvHeader->size); // printf("recv HeaderInfo: OP: %d ,size : %d /n",recvHeader->OP,recvHeader->size); // if(recvHeader->size > 0 && recvHeader->size < BUFFER_MAX_SIZE) // { // bytesRecv = recv(sClient,buffer,recvHeader->size,0); // if(bytesRecv <= 0 || bytesRecv == WSAECONNRESET) // { // printf("client disconnect with server(%d)/n",WSAGetLastError()); // break; // } // //打印数据信息 // convertDataAndPrint(recvHeader->OP,buffer,recvHeader->size); // } //} //==================================== host = gethostbyaddr((char *)&remoteAddr.sin_addr.s_addr,4,AF_INET); printf("/nClient(%s:%s)connect with server!/n", host->h_name, inet_ntoa(remoteAddr.sin_addr)); //==================================== if(socketLen > BACKLOG) { printf("go beyond the limit 10!/n"); sClient = NULL; break; } //创建线程 HANDLE hThread; socketArr[socketLen] = sClient; hThread = (HANDLE)_beginthreadex(NULL,0,SockThread,(void *)sClient,0,NULL); //用于存储socket的数组下标++ socketLen++; } closesocket(ListenSocket); WSACleanup(); return; } //接发数据 unsigned __stdcall SockThread(void *socket) { int cnInt = socketLen - 1; int bytesRecv = SOCKET_ERROR; Header *recvHeader = (Header *)malloc(HEADER_LEN); char* buffer; //char* tmpBuf; char* clientIP; struct sockaddr_in client_message; int client_len = sizeof(struct sockaddr_in); int dataLen; //==================获得连接上来的客户端信息=================== bytesRecv = getsockname((SOCKET)socket,(struct sockaddr *)&client_message,&client_len); clientIP = inet_ntoa(client_message.sin_addr); //==================获得连接上来的客户端信息=================== //暂存接收的数据 buffer = (char *)malloc(BUFFER_MAX_SIZE); while(1) { bytesRecv = recv((SOCKET)socket,(char*)recvHeader,HEADER_LEN,0); if(bytesRecv <= 0 || bytesRecv == WSAECONNRESET) { printf("server : Client (%s) connection closed/n",clientIP); closesocket(socketArr[cnInt]); socketArr[cnInt] = NULL; break; } //将网络序转换为本地序 recvHeader->OP = ntohl(recvHeader->OP); recvHeader->size = ntohl(recvHeader->size); printf("/n=======recv command:%d ; dataLen : %d./n",recvHeader->OP,recvHeader->size); if(recvHeader->size > 0 && recvHeader->size < BUFFER_MAX_SIZE) { bytesRecv = recv((SOCKET)socket,buffer,recvHeader->size,0); if(bytesRecv <= 0 || bytesRecv == WSAECONNRESET) { if(bytesRecv == 0) { printf("server : SendMsg Info recv failed/n"); } else if(bytesRecv < 0) { printf("server: recv data failed! disconnect with client(%s)/n",clientIP); } break; } //===============send to other client begin================== if(recvHeader->OP == 0 || recvHeader->OP == 1) { for(int i = 0 ; i < socketLen; i++) { if((SOCKET)socket != socketArr[i]) { int dataLen = recvHeader->size; recvHeader->OP = htonl(recvHeader->OP); recvHeader->size = htonl(recvHeader->size); send((SOCKET)socketArr[i],(char *)recvHeader,HEADER_LEN,0); if((send((SOCKET)socketArr[i],buffer,dataLen,0)) < 0 ) { printf("server: client(%s) disconnect with server!/n",clientIP); break; } } } } else { printf("Send OP error.you must select it which is 0 or 1/n"); } //===============send to other client end=================== //buffer中仅有dataInfo没有headerInfo convertDataAndPrint(recvHeader->OP,buffer,recvHeader->size); } else { if(recvHeader->size > 0) { printf("The client (%s) send the dataLen(%d) larger buffer size(%d).please input small again!/n", clientIP,recvHeader->size,BUFFER_MAX_SIZE); } else { printf("The client (%s) send the dataLen(%d) less than 0./ndisconnection with server/n", clientIP,recvHeader->size); //break; } } //memset(buffer,0,recvHeader->size); } free(buffer); _endthreadex( 0 ); return 0; }