#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)
//Unicode轉(zhuǎn)換為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轉(zhuǎn)換為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主機(jī)序轉(zhuǎn)換為網(wǎng)絡(luò)序
void unih2n(LPWSTR uniStr)
{
for(; *uniStr != 0; uniStr++){
*uniStr = htons((short)*uniStr);
}
}
//Unicode網(wǎng)絡(luò)序轉(zhuǎn)換為主機(jī)序
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]);
}
//構(gòu)建數(shù)據(jù)函數(shù) retCmdId根據(jù)Header中的OP來的。把數(shù)據(jù)構(gòu)建到buffer(包含頭信息和數(shù)據(jù)信息)中
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;
}
//構(gòu)建數(shù)據(jù)函數(shù) retCmdId根據(jù)Header中的OP來的。把現(xiàn)有數(shù)據(jù)構(gòu)建到buffer(包含頭信息和數(shù)據(jù)信息)中
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轉(zhuǎn)換為L(zhǎng)og結(jié)構(gòu)
Log * pTmpLog = (Log *)(buffSource);
//========================================
pLog->timeLen = htonl(pTmpLog->timeLen);
pLog->userNameLen = htonl(pTmpLog->userNameLen);
//========================================
dataLen = LOG_INFO_TIME_OFFSET;
//找到buffSource對(duì)應(yīng)time的OFFSET。
tmpUniStr = (LPWSTR)(buffSource + LOG_INFO_TIME_OFFSET);
uniChar = tmpUniStr[pTmpLog->timeLen];
tmpUniStr[pTmpLog->timeLen] = 0;
//將tmpUniStr里的值轉(zhuǎn)換成本地
unin2h(tmpUniStr);
//將Unicode轉(zhuǎn)換為Ascii。并賦值給tmp數(shù)組
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里的值轉(zhuǎn)換成本地
unin2h(tmpUniStr);
//將Unicode轉(zhuǎn)換為Ascii。并賦值給tmp數(shù)組
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對(duì)應(yīng)userName的OFFSET。
tmpUniStr = (LPWSTR)(buffSource + SENDMSG_INFO_USERNAME_OFFSET);
uniChar = tmpUniStr[pTmpSendMsg->userNameLen];
tmpUniStr[pTmpSendMsg->userNameLen] = 0;
//將tmpUniStr里的值轉(zhuǎn)換成本地
unin2h(tmpUniStr);
//將Unicode轉(zhuǎn)換為Ascii。并賦值給tmp數(shù)組
uni2str(tmpUniStr,tmp);
tmpUniStr[pTmpSendMsg->userNameLen] = uniChar;
uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_USERNAME_OFFSET);
str2uni(tmp,uniStr);
unih2n(uniStr);
dataLen += pSendMsg->userNameLen * 2;
//找到buffSource對(duì)應(yīng)sendMsg的OFFSET。
tmpUniStr = (LPWSTR)(buffSource + SENDMSG_INFO_SENDMSG_OFFSET(pTmpSendMsg));
uniChar = tmpUniStr[pTmpSendMsg->userNameLen];
tmpUniStr[pTmpSendMsg->userNameLen] = 0;
//將tmpUniStr里的值轉(zhuǎn)換成本地
unin2h(tmpUniStr);
//將Unicode轉(zhuǎn)換為Ascii。并賦值給tmp數(shù)組
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對(duì)應(yīng)time的OFFSET。
tmpUniStr = (LPWSTR)(buffSource + SENDMSG_INFO_TIME_OFFSET(pTmpSendMsg));
tmpUniStr[pTmpSendMsg->userNameLen] = 0;
//將tmpUniStr里的值轉(zhuǎn)換成本地
unin2h(tmpUniStr);
//將Unicode轉(zhuǎn)換為Ascii。并賦值給tmp數(shù)組
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;
}
//轉(zhuǎn)換所接收數(shù)據(jù),并打印輸出,不包含頭信息
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("錯(cuò)誤:數(shù)據(jù)解析越界,時(shí)間長(zhǎng)度無效(%d)/n", pLog->timeLen);
return;
}
//time
uniStr = (LPWSTR)(buff + LOG_INFO_TIME_OFFSET);
//這里是把uniStr所切取的字符串最后一位字符給uniChar(因?yàn)樵撐簧峡赡苁窍乱粋€(gè)數(shù)據(jù)的值)。
//再讓uniStr最后一位為0,成為一個(gè)字符串。最后將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("錯(cuò)誤:數(shù)據(jù)解析越界,姓名長(zhǎng)度無效(%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("錯(cuò)誤:數(shù)據(jù)解析越界,姓名長(zhǎng)度無效(%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("錯(cuò)誤:數(shù)據(jù)解析越界,信息長(zhǎng)度無效(%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("錯(cuò)誤:數(shù)據(jù)解析越界,時(shí)間長(zhǎng)度無效(%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 版本號(hào),WSAData為WSADATA結(jié)構(gòu)對(duì)象
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()/n");
//創(chuàng)建套接字
SOCKET ConnectSocket;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld/n", WSAGetLastError());
WSACleanup();
return;
}
//填寫遠(yuǎn)程地址信息
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_port = htons( 27015 );
//填寫服務(wù)器程序所在的機(jī)器的IP地址
clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
//連接服務(wù)器端
if ( connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR)
{
printf( "Failed to connect./n" );
WSACleanup();
return;
}
//創(chuàng)建句柄
HANDLE hCliThread;
unsigned threadID;
//產(chǎn)生線程 3.線程創(chuàng)建后調(diào)用的函數(shù),4.該函數(shù)的參數(shù),6.線程ID 方便對(duì)線程進(jìn)行管理
hCliThread = (HANDLE)_beginthreadex(NULL,0,SendThread,(void *)ConnectSocket,0,&threadID);
int bytesRecv = 0;
//創(chuàng)建一個(gè)接收的結(jié)構(gòu)體,用于接收并解析
Header *recvHeader = (Header *)malloc(HEADER_LEN);
char* buffer;
buffer = (char *)malloc(BUFFER_MAX_SIZE);
for(;;)//recevice data from server
{
//接收連接上來的服務(wù)端,在客戶器端創(chuàng)建一個(gè)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;
}
//打印數(shù)據(jù)信息
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");
//==================登錄 并發(fā)送登錄信息=================
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);
//==================登錄 并發(fā)送登錄信息 結(jié)束=================
//循環(huán)發(fā)送數(shù)據(jù)信息給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);
}
//結(jié)束線程
free(buffer);
_endthreadex( 0 );
return 0;
}
//構(gòu)建數(shù)據(jù)函數(shù) retCmdId根據(jù)Header中的OP來的。把現(xiàn)有數(shù)據(jù)構(gòu)建到buffer(包含頭信息和數(shù)據(jù)信息)中
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轉(zhuǎn)換為L(zhǎng)og結(jié)構(gòu)
Log * pTmpLog = (Log *)(buffSource);
//========================================
pLog->timeLen = htonl(pTmpLog->timeLen);
pLog->userNameLen = htonl(pTmpLog->userNameLen);
//========================================
dataLen = LOG_INFO_TIME_OFFSET;
//找到buffSource對(duì)應(yīng)time的OFFSET。
tmpUniStr = (LPWSTR)(buffSource + LOG_INFO_TIME_OFFSET);
uniChar = tmpUniStr[pTmpLog->timeLen];
tmpUniStr[pTmpLog->timeLen] = 0;
//將tmpUniStr里的值轉(zhuǎn)換成本地
//*****************unin2h(tmpUniStr);
//將Unicode轉(zhuǎn)換為Ascii。并賦值給tmp數(shù)組
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里的值轉(zhuǎn)換成本地
unin2h(tmpUniStr);
//將Unicode轉(zhuǎn)換為Ascii。并賦值給tmp數(shù)組
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對(duì)應(yīng)userName的OFFSET。
tmpUniStr = (LPWSTR)(buffSource + SENDMSG_INFO_USERNAME_OFFSET);
uniChar = tmpUniStr[pTmpSendMsg->userNameLen];
tmpUniStr[pTmpSendMsg->userNameLen] = 0;
//將tmpUniStr里的值轉(zhuǎn)換成本地
unin2h(tmpUniStr);
//將Unicode轉(zhuǎn)換為Ascii。并賦值給tmp數(shù)組
uni2str(tmpUniStr,tmp);
tmpUniStr[pTmpSendMsg->userNameLen] = uniChar;
uniStr = (LPWSTR)(tmpBuf + SENDMSG_INFO_USERNAME_OFFSET);
str2uni(tmp,uniStr);
unih2n(uniStr);
dataLen += pSendMsg->userNameLen * 2;
//找到buffSource對(duì)應(yīng)sendMsg的OFFSET。
tmpUniStr = (LPWSTR)(buffSource + SENDMSG_INFO_SENDMSG_OFFSET(pTmpSendMsg));
uniChar = tmpUniStr[pTmpSendMsg->userNameLen];
tmpUniStr[pTmpSendMsg->userNameLen] = 0;
//將tmpUniStr里的值轉(zhuǎn)換成本地
unin2h(tmpUniStr);
//將Unicode轉(zhuǎn)換為Ascii。并賦值給tmp數(shù)組
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對(duì)應(yīng)time的OFFSET。
tmpUniStr = (LPWSTR)(buffSource + SENDMSG_INFO_TIME_OFFSET(pTmpSendMsg));
tmpUniStr[pTmpSendMsg->userNameLen] = 0;
//將tmpUniStr里的值轉(zhuǎn)換成本地
unin2h(tmpUniStr);
//將Unicode轉(zhuǎn)換為Ascii。并賦值給tmp數(shù)組
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;
}
//轉(zhuǎn)換所接收數(shù)據(jù),并打印輸出,不包含頭信息
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("錯(cuò)誤:數(shù)據(jù)解析越界,時(shí)間長(zhǎng)度無效(%d)/n", pLog->timeLen);
return;
}
//time
uniStr = (LPWSTR)(buff + LOG_INFO_TIME_OFFSET);
//這里是把uniStr所切取的字符串最后一位字符給uniChar(因?yàn)樵撐簧峡赡苁窍乱粋€(gè)數(shù)據(jù)的值)。
//再讓uniStr最后一位為0,成為一個(gè)字符串。最后將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("錯(cuò)誤:數(shù)據(jù)解析越界,姓名長(zhǎng)度無效(%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("錯(cuò)誤:數(shù)據(jù)解析越界,姓名長(zhǎng)度無效(%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("錯(cuò)誤:數(shù)據(jù)解析越界,信息長(zhǎng)度無效(%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("錯(cuò)誤:數(shù)據(jù)解析越界,時(shí)間長(zhǎng)度無效(%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 版本號(hào),WSAData為WSADATA結(jié)構(gòu)對(duì)象
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
{
printf("Error at WSAStartup()/n");
return;
}
//創(chuàng)建套接字
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結(jié)構(gòu)
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);
//綁定這個(gè)套接字到一個(gè)本地地址
if (bind( ListenSocket,(SOCKADDR*)&service,sizeof(service)) == SOCKET_ERROR)
{
printf("bind() failed./n");
closesocket(ListenSocket);
WSACleanup();
return;
}
// 進(jìn)入監(jiān)聽模式
if (listen( ListenSocket, BACKLOG ) == SOCKET_ERROR)
{
printf("Error listening on socket./n");
closesocket(ListenSocket);
WSACleanup();
return ;
}
printf("listening...../n");
while(true)
{
//循環(huán)接收連接上來的客戶端
sClient = accept(ListenSocket,(SOCKADDR*)&remoteAddr,&nAddrLen);
if(sClient == INVALID_SOCKET)
{
printf("Failed accept!/n");
continue;
}
//else
//{
// int bytesRecv = 0;
// //創(chuàng)建一個(gè)接收的結(jié)構(gòu)體,用于接收并解析
// 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;
// }
// //打印數(shù)據(jù)信息
// 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;
}
//創(chuàng)建線程
HANDLE hThread;
socketArr[socketLen] = sClient;
hThread = (HANDLE)_beginthreadex(NULL,0,SockThread,(void *)sClient,0,NULL);
//用于存儲(chǔ)socket的數(shù)組下標(biāo)++
socketLen++;
}
closesocket(ListenSocket);
WSACleanup();
return;
}
//接發(fā)數(shù)據(jù)
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);
//==================獲得連接上來的客戶端信息===================
//暫存接收的數(shù)據(jù)
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;
}
//將網(wǎng)絡(luò)序轉(zhuǎn)換為本地序
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;
}
新聞熱點(diǎn)
疑難解答
圖片精選