欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java调用c程序通信示例代码

程序员文章站 2023-12-20 20:53:10
复制代码 代码如下://===============client struct================#pragma pack(push,4) #define...

复制代码 代码如下:

//===============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;
}

上一篇:

下一篇: