java调用c程序通信示例代码
//===============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;
}