代码如下:
//===============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;
}