#include
#include
#include
#include
#include
#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
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;
}