代碼如下:
//===============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;
}
復制代碼代碼如下:
#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;
}