CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  网络编程

麻烦!麻烦!(传输两个结构体)高手们快来帮小弟一把

楼主ff324()2002-12-14 15:46:32 在 VC/MFC / 网络编程 提问

现需要传输两个结构体,比如HEAD和DATA。我把HEAD强制转换成char   *sendstr1,然后把DATA转换成char   *sendstr2。如果把这两个结构体分两步send出去,服务器方接收以后强制转换成结构体形式,可以得到正确结果。但分两次send存在延时问题,现在想一次send把两个结构体发出去,怎么实现?我的做法是把sendstr1和sendstr2整和在一起发送,但那样发送好象有些问题,服务器方接收不到正确信息。代码我给拉过来,大伙帮忙分析一下。  
  问题点数:50、回复次数:10Top

1 楼ff324()回复于 2002-12-14 15:48:30 得分 0

client端代码:  
  #include   <stdio.h>  
  #include   <stdlib.h>  
  #include   <string.h>  
  #include   <winsock.h>  
  #define   SERVER "127.0.0.1"  
  #define   PORT 5250    
   
  struct   HEAD  
  {  
  char   h1[4];  
  char   h2[6];  
  };  
   
  struct   DATA  
  {  
  char   d1[4];  
  char   d2[6];  
  };  
   
  int   main(   )  
  {  
  int   sockfd,n;  
  struct   sockaddr_in   ser_addr;  
  char   *sendstr1;    
  char   *sendstr2;    
  struct   HEAD   *head;    
  struct   DATA   *data;    
  head=(struct   HEAD*)malloc(sizeof(struct   HEAD));    
  data=(struct   DATA*)malloc(sizeof(struct   DATA));    
  WSADATA   wsadata;    
  WSAStartup(MAKEWORD(2,2),   &wsadata);    
  strcpy(head->h1,"6");    
  strcpy(head->h2,"8");      
  sendstr1=(char   *)head;  
  strcpy(data->d1,"16");    
  strcpy(data->d2,"18");    
  sendstr2=(char   *)data;  
  strncat(sendstr1,sendstr2,sizeof(struct   HEAD));  
  int   length=(sizeof(struct   HEAD)+sizeof(struct   DATA));  
   
  memset(&ser_addr,0,sizeof(ser_addr));  
  ser_addr.sin_family   =   AF_INET;  
  ser_addr.sin_addr.s_addr   =   inet_addr(SERVER);  
  ser_addr.sin_port   =   htons(PORT);  
  sockfd=socket(AF_INET,SOCK_STREAM,0);  
  if   (sockfd<0)   {    
  printf("0x%x:%d   error\n",ntohl(ser_addr.sin_addr.s_addr),ntohs(ser_addr.sin_port));  
  exit(1);  
  }  
  if(connect(sockfd,(struct   sockaddr*)&ser_addr,sizeof(ser_addr))<0){  
  printf("connect   error\n");  
  exit(1);  
  }  
  printf("connected\n");  
   
  if(send(sockfd, sendstr1,length,0)<0){  
  printf("Send   error!\n");  
  exit(0);  
  }  
  printf("Send   ok!\n");  
     
  WSACleanup();  
  }  
   
   
  server端代码如下:  
  #include   <stdio.h>  
  #include   <stdlib.h>  
  #include   <string.h>  
  #include   <winsock.h>  
  #define   PORT     5250  
   
  struct   HEAD  
  {  
  char   h1[4];  
  char   h2[6];  
  };  
   
  struct   DATA  
  {  
  char   d1[4];  
  char   d2[6];  
  };  
  int   main(   )  
  {  
  int   sockfd,new_fd,n,sin_size;  
  struct   sockaddr_in   ser_addr;  
  struct   sockaddr_in   clt_addr;    
  char   recvs[100];  
  struct   HEAD   *head;    
  struct   DATA   *data;    
  char   s1[10];  
  char   s2[10];  
  char   n1[10];  
  char   n2[10];  
  WSADATA   wsadata;  
  WSAStartup(MAKEWORD(2,2),   &wsadata);    
  head=(struct   HEAD*)malloc(sizeof(struct   HEAD));    
  data=(struct   DATA*)malloc(sizeof(struct   DATA));    
   
  memset(&ser_addr,0,sizeof(ser_addr));  
  sockfd=socket(AF_INET,SOCK_STREAM,0);  
  ser_addr.sin_family   =   AF_INET;  
  ser_addr.sin_addr.s_addr=htonl(INADDR_ANY);  
  ser_addr.sin_port   =   htons(PORT);  
  if(ser_addr.sin_port==0){  
  printf("Bad   server   port!   %d!\n",ntohs(ser_addr.sin_port));  
  return   -2;  
  }  
  if   (sockfd<0)   {    
  printf("0x%x:%d   error\n",ntohl(ser_addr.sin_addr.s_addr),ntohs(ser_addr.sin_port));  
  exit(1);  
  }  
  if   (bind(sockfd,   (struct   sockaddr   *)&ser_addr,   sizeof(ser_addr)))   {    
  printf("Cannot   bind   server   port!");    
   
  return   -4;    
  }    
   
  listen(sockfd,100);  
  while   (1)  
  {    
  sin_size=sizeof(struct   sockaddr_in);  
  printf("Listening   at:   0x%x:%d!\n",ntohl(ser_addr.sin_addr.s_addr),ntohs(ser_addr.sin_port));  
  new_fd=accept(sockfd,(struct   sockaddr*)&clt_addr,&sin_size);  
   
  if((n=recv(new_fd,recvs,sizeof(struct   HEAD),0))==0)   {  
  printf("read   error!\n");  
  }  
  recvs[n]=0;  
  head=(struct   HEAD*)recvs;    
  strcpy(s1,head->h1);    
  strcpy(s2,head->h2);    
   
  if((n=recv(new_fd,recvs,sizeof(struct   DATA),0))==SOCKET_ERROR)   {  
   
  printf("read   error:%d\n",WSAGetLastError());  
  }  
  recvs[n]=0;  
  data=(struct   DATA*)recvs;  
  strcpy(n1,data->d1);  
  strcpy(n2,data->d2);  
  printf("read   ok!\n   %s\n",n1);  
  printf("read   ok!\n   %s\n",n2);  
   
   
  }  
  WSACleanup();  
   
  }  
   
   
  Top

2 楼ff324()回复于 2002-12-14 15:52:06 得分 0

怎么这么长,忘了写注释了,大伙主要看一下send和recv及里面的参数吧Top

3 楼HongHuer(Hello,world.)回复于 2002-12-14 16:33:48 得分 10

struct   HEAD  
  {  
  char   h1[4];  
  char   h2[6];  
  };  
   
  struct   DATA  
  {  
  char   d1[4];  
  char   d2[6];  
  };  
   
  struct   NEWS  
  {  
              struct   HEAD   head;  
              struct   DATA   data;  
  };  
   
   
  send   and   receive   the   struct   NEWS  
   
  Top

4 楼cooljjyy(叽叽歪歪)回复于 2002-12-14 16:42:24 得分 10

不能想得太单纯,虽然你是分两次发送,但是服务器说不定只收了一次,比如你两次分别发送2和2字节,服务器可能收到1和3字节两次,也可能是一次收到4字节,用楼上的方法可以,但是最终为了你的程序安全考虑,recv数据的时候一定要循环进行,直到判断收到所有的字节为止,因为甚至可能你能recv到4个1字节的数据Top

5 楼omale(代码机器.net)回复于 2002-12-14 21:45:11 得分 5

同意Top

6 楼anyiflyer(代码在我心中!)回复于 2002-12-15 14:20:39 得分 25

如果是LAN,不可能出现先发送的数据后收到的情况,但是WAN就可能出现了.但是如果是TCP协议,TCP自己会重组的.一般地说,发送1K的数据是安全的,因为TCP的windows是8K,另外,跟你发送的数据是什么类型没有一点关系,在TCP协议中只认识字节,或者说TCP只有字节的概念,它也不关心数据是什么类型.  
  struct   type1{  
          int     i   ;  
          long   k   ;  
  }*ptype1;  
   
  struct   type2{  
          char   str[128];  
          float   f;  
  }*ptype2;  
   
  char   buffer[1024];  
   
      ptype1   =   (   struct   type1   *)buffer   ;  
      ptype1->i   =   100   ;  
      ptype1->k   =   5000   ;  
   
      ptype2   =   (   struct   type2   *)(buffer   +   sizeof(   struct   type1));  
      sprintf(   ptype2->str,   "I   love   u");  
      ptype2->f   =   122.2;  
   
      ptcpsocket->send(   buffer,   sizeof(   struct   type1   )   +   sizeof(   struct   type2   ));  
  我一直是用这种方法的,而且也没有出现过问题.下面是比较详细的代码,各位看看,请多多指教.  
   
  //   data.h:   interface   for   the   CData   class.  
  //  
  //////////////////////////////////////////////////////////////////////  
   
  #if   !defined(AFX_DATA_H__F849DA10_B160_11CF_BC5B_5254AB4B2098__INCLUDED_)  
  #define   AFX_DATA_H__F849DA10_B160_11CF_BC5B_5254AB4B2098__INCLUDED_  
   
  #if   _MSC_VER   >   1000  
  #pragma   once  
  #endif   //   _MSC_VER   >   1000  
  #include   "define.h"  
   
  class   CData  
  {  
  public:  
  CData();  
  virtual   ~CData();  
  //methods   and   operations  
  public:  
  virtual   void   Build();                           //将数据缓冲区中的数据解码到成员中  
  virtual   BOOL   Load();                             //填充数据缓冲区  
  //data   members  
  public:  
  BYTE         type   ;                                         //消息类型  
  BYTE         WndIndex;                                   //处理该消息的窗口句柄索引  
  DWORD       flag         ;                                   //消息标记  
   
  UINT         dstPort   ;                                   //目的IP地址  
  UINT         dstIP   ;                                       //目的端口号  
  char         buffer[Max_Data_Length]   ;   //数据缓冲区  
  WORD         buf_len   ;                                   //数据缓冲区中数据长度  
  WORD         buf_offset;                               //数据缓冲区中特殊数据的偏移  
   
  private:  
   
  protected:  
   
  };  
   
  inline   void   CopyData(CData   *dst,CData   *src)  
  {  
  for   (   int   i   =   0   ;i   <   src->buf_len   ;   i   ++   )  
  dst->buffer[i]   =   src->buffer[i]   ;  
  dst->type               =   src->type               ;  
  dst->dstIP             =   src->dstIP             ;  
  dst->dstPort         =   src->dstPort         ;  
  dst->buf_len         =   src->buf_len         ;  
  dst->buf_offset   =   src->buf_offset   ;  
  dst->WndIndex       =   src->WndIndex       ;  
  }  
   
   
  #endif   //   !defined(AFX_DATA_H__F849DA10_B160_11CF_BC5B_5254AB4B2098__INCLUDED_)  
  /////////////////////////////////////////////////////////////////  
  //   data.cpp:   implementation   of   the   CData   class.  
  //  
  //////////////////////////////////////////////////////////////////////  
   
  #include   "stdafx.h"  
  #include   "data.h"  
  #include   "define.h"  
   
  #ifdef   _DEBUG  
  #undef   THIS_FILE  
  static   char   THIS_FILE[]=__FILE__;  
  #define   new   DEBUG_NEW  
  #endif  
   
  //////////////////////////////////////////////////////////////////////  
  //   Construction/Destruction  
  //////////////////////////////////////////////////////////////////////  
   
  CData::CData()  
  {  
  type               =   MSG_USER_DEFINE   ;  
  WndIndex       =   0   ;  
  dstPort         =   DEFAULT_DST_PORT   ;  
  dstIP             =   inet_addr(DEFAULT_DST_IP);  
  buf_len         =   0   ;  
  buf_offset   =   0   ;  
  WndIndex       =   -1;  
  flag               =   0   ;  
  memset(buffer,0,Max_Data_Length);  
  }  
   
  CData::~CData()  
  {  
   
  }  
   
   
  void   CData::Build()  
  {  
  char   *cp   =   NULL   ;  
   
  cp   =   buffer   ;  
   
  //开头是固定数据  
  *(BYTE   *)cp   =   type   ;             //消息类型  
  cp   +=   sizeof(BYTE)   ;  
   
  *(BYTE   *)cp   =   WndIndex   ;     //窗口句柄索引  
  cp   +=   sizeof(BYTE);  
   
  *(DWORD   *)cp   =   flag   ;           //消息标记  
  cp   +=   sizeof(DWORD)   ;  
   
          //以下是附加数据的开始地址  
  buf_len         =   cp   -   buffer   ;  
  buf_offset   =   cp   -   buffer   ;//用户数据的偏移量  
  }  
   
  BOOL   CData::Load()  
  {  
  char   *cp     =   buffer   ;  
   
  type   =   *(BYTE   *)cp   ;             //   消息类型  
  cp   +=   sizeof(BYTE)   ;  
   
  WndIndex   =   *cp   ;                     //窗口句柄索引  
  if(   WndIndex   <   0   &&   WndIndex   >=   MaxRecvWndCount   )  
  return   FALSE   ;  
  cp   +=   sizeof(WndIndex);  
   
  flag   =   *(DWORD   *)cp;  
  cp   +=   sizeof(DWORD);  
   
  buf_offset   =   cp   -   buffer   ;//用户数据的偏移量  
   
  if(   buf_offset   <=   buf_len   )return   TRUE   ;  
  return   FALSE   ;  
  }  
   
  //////////////////////////////////////////////////////  
  class   CMsgChat   :   public   CData  
  {  
  public:  
  CMsgChat();  
  virtual   ~CMsgChat()       ;  
  public:  
  virtual   BOOL   Load()       ;  
  virtual   void   Build()   ;  
  public:  
  WORD         srcID         ;           //source   ID  
  WORD         dstID         ;           //destination   ID  
  WORD         nLen           ;           //发送内容长度  
  char         content[Max_Content_Length];     //内容  
  };  
  //////////////////////////////////////////////////////  
  /////////////////////////////////////////////////////////  
  //               implementation   of   the   CMsgChat   class.                   //  
  /////////////////////////////////////////////////////////  
  /********************************************************  
  Construction   CMsgRegist   Class's  
  *********************************************************/  
  CMsgChat::CMsgChat()  
  {  
  nLen   =   0   ;  
  srcID=   0   ;  
  memset(content,0,Max_Content_Length);  
  }  
   
  CMsgChat::~CMsgChat()  
  {  
   
  }  
  /********************************************************  
  Encode   CMsgChat   Class's   buffer  
  *********************************************************/  
  void   CMsgChat::Build()  
  {  
  CData::Build();  
  char   *cp   =   (char   *)(buffer   +   buf_offset   );  
  *(WORD   *)cp   =   srcID   ;  
  cp   +=   sizeof(WORD)       ;  
  *(WORD   *)cp   =   dstID   ;  
  cp   +=   sizeof(WORD)       ;  
  *(WORD   *)cp   =   nLen       ;  
  cp   +=   sizeof(WORD)       ;  
  memcpy(cp,content,nLen);  
  cp   +=   nLen   ;  
  buf_len   =   cp   -   buffer   ;  
  }  
  /********************************************************  
  Decode   CMsgChat   Class's   buffer  
  *********************************************************/  
  BOOL   CMsgChat::Load()  
  {  
  if(   !CData::Load()   )  
  return   FALSE   ;  
  char   *cp   =   (char   *)(buffer   +   buf_offset   );  
  srcID   =   *(WORD   *)cp   ;  
  cp   +=   sizeof(WORD)       ;  
  dstID   =   *(WORD   *)cp   ;  
  cp   +=   sizeof(WORD)       ;  
  nLen   =   *(WORD   *)cp       ;  
  cp   +=   sizeof(WORD)       ;  
  if(nLen   >   Max_Content_Length   )  
  memcpy(content,cp,Max_Content_Length);  
  else   memcpy(content,cp,nLen);  
  cp   +=   nLen   ;  
   
  if(   cp   -   buffer   >   buf_len   )  
  return   FALSE   ;  
  return   TRUE   ;  
  }  
   
   
   
  Top

7 楼ff324()回复于 2002-12-16 17:17:29 得分 0

楼上几位,特别是西门吹雪,多谢了!结构体传输的问题解决了,不过现在又  
  有新问题了,怎么用c语言编写的socket传输jpj文件或是几兆的大文件。你们去我的新贴看一下吧。多多谢!!!  
  http://expert.csdn.net/Expert/topic/1266/1266170.xml?temp=.9910395Top

8 楼anyiflyer(代码在我心中!)回复于 2002-12-18 12:42:52 得分 0

给分啊.Top

9 楼ff324()回复于 2002-12-20 09:53:02 得分 0

我真的已经给分了,奇怪csdn没有显示分值。可能操作有误?我是csdn的新生,初来乍到,人生地不熟?没给成分,楼上几位莫见怪!放心,我会在以后补偿你的,西门大哥。  
  Top

10 楼anyiflyer(代码在我心中!)回复于 2002-12-26 13:04:34 得分 0

呵呵,没有关系的.CSDN是做的不够好,我都不知道我的分是在什么时候给的,应该显示时间的啊.Top

相关问题

  • 高手相助!网络传输结构体的问题。
  • windows sockets编程,如何用send()或sendto()传输一个结构体?
  • 用ARMV41-UNKNOWN_LINUX-GCC编译出的Socket程序传输结构体出问题,请大家帮忙分析一下
  • 结构体中有无符号的整型,怎么转换成char*在网络中传输啊?
  • 在结构体里面定义一个大的数组,可是有麻烦了!
  • 三层结构大数据量传输问题
  • /*================= socket传输中如何传递一个结构? ==================*/
  • B/S结构中数据的加密传输的问题
  • 没事多讨论:b/s结构软件中数据传输技术
  • 没事多讨论:c/s结构软件中数据传输技术

关键词

  • 结构
  • 服务器
  • 转换
  • 数据
  • csdn
  • ser
  • sendstr
  • addr
  • 传输
  • head

得分解答快速导航

  • 帖主:ff324
  • HongHuer
  • cooljjyy
  • omale
  • anyiflyer

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo