小弟现在做了一个登陆程序,
登陆包设计为:
//包头定义
typedef struct

  DWORD dwCMD;
  DWORD dwLength;//整个数据包的长度 = 数据包的包头 + 数据包的包体
}PACKAGE_HEAD;//登陆包
typedef struct
{
   char            *Username;
   char            *password;
} LOGIN_PACKAGE_BODY;//服务器发送给客户端一个登陆回应包,来说明本次登陆是否成功
typedef struct

  int result;//该值由定义的登陆错误代码,返回给客户端
}LOGIN_PACKAGE_RESP;//完整的数据包的定义
typedef  struct

  PACKAGE_HEAD  PACKAGEHEAD;
  union
  {
    LOGIN_PACKAGE_BODY       stLogin;
    LOGIN_PACKAGE_RESP   stLoginResp;
   };
}PACKAGE;//客户端
CString  str1,str2;
        DWORD       SendBytes = 0;//发送的字节数目
WSABUF      wsabuff;//发送数据的缓冲区
         SOCKADDR_IN   Addrinfo;
WORD        port = 5050;
DWORD       dwFlags = 0; //连接服务端
 Addrinfo.sin_family = AF_INET;
 Addrinfo.sin_addr.s_addr =inet_addr("192.168.1.4");
 Addrinfo.sin_port = htons(port);         int rc = WSAConnect(m_socket,(sockaddr*)&Addrinfo,sizeof(Addrinfo),NULL,NULL,NULL,NULL);        //首先读取两个EDIT框里的数据
         GetDlgItem(IDC_EDIT1)->GetWindowText(str1);//获取EDIT1中的数据
         GetDlgItem(IDC_EDIT2)->GetWindowText(str2);//获取EDIT2中的数据
  
         PACKAGE     sendMsg;//发送给服务端的数据
sendMsg.PACKAGEHEAD.dwCMD  = CMD_Login; //包头里的命令
         sendMsg.stLogin.Username   = str1.GetBuffer (str1.GetLength ());
sendMsg.stLogin.password   = str2.GetBuffer (str2.GetLength ());
sendMsg.PACKAGEHEAD.dwLength = sizeof(sendMsg);        PACKAGE *p = &sendMsg; wsabuff.buf = (char*)p;        wsabuff.len = sizeof(sendMsg);
   
        WSASend(m_socket,&wsabuff,1,&SendBytes,dwFlags,NULL,NULL);服务端代码:
        #define   SOCKET_BUFF_SIZE   1024
       #define   DEFAULT_BUFF_SIZE  4096
         int             rc = 0;
DWORD            len = 0;  
SOCKET               *ps;
char           PackageBuff[SOCKET_BUFF_SIZE];//套接字缓冲区
WSABUF         DataBuff;
DWORD          dwFlags = 0;
char           *tempbuff = NULL;
char           *Finalbuff = NULL;
char           HandleBuff[DEFAULT_BUFF_SIZE];//拼包整理缓冲区
int            DataBuffCount = 0;//拼包整理缓冲区里未处理数据的字节数
int            StartPos = 0;//要放入拼包数据缓冲区的起始地址        ps = (SOCKET *)lpParam;//工作线程的参数是套接字     while (1)
     {
         DataBuff.len = SOCKET_BUFF_SIZE;        DataBuff.buf = PackageBuff;        DWORD         RecvBytes = 0;        while(RecvBytes < sizeof(PACKAGE_HEAD) )  
{ //当收到的数据小于包头,就循环
  WSARecv(*ps, &DataBuff, 1,&RecvBytes,&dwFlags,NULL,NULL);
} //将数据拷贝到整理缓冲区尾部
StartPos = DataBuffCount;//获得缓冲区中的起始地址
         memcpy(HandleBuff + StartPos,DataBuff.buf,RecvBytes);//将本次接收的数据全部拷贝到整理缓冲区内
DataBuffCount += RecvBytes;//未处理的数据量要增加 //处理包头数据
PACKAGE_HEAD    *pHead = new PACKAGE_HEAD ;
        memcpy(pHead,HandleBuff,sizeof(PACKAGE_HEAD));//从缓冲区中取得一个包头的长度的数据         //判断拼包整理缓冲区里的数据是否够一个完整的包
          if(sizeof(HandleBuff) >=  pHead->dwLength )
{ //如果够一个完整的包,则处理该包,处理完毕后要将剩余的数据向前移动
   char *tempbuff =(char *) malloc(pHead->dwLength);//分配整个包大小的内存空间
            memmove(tempbuff,HandleBuff,pHead->dwLength);//将完整的包体数据存入缓冲区

  //包体覆盖包头数据
  int ivalue = pHead->dwLength-sizeof(PACKAGE_HEAD); //获得包体的大小
  for(int i=0;i<ivalue;i++)
  { 
   tempbuff[i]=tempbuff[i+sizeof(PACKAGE_HEAD)];  
          }           //形成最终的包体数据
   char *Finalbuff =(char *) malloc(pHead->dwLength-sizeof(PACKAGE_HEAD));//分配包体大小的内存空间
            memcpy(Finalbuff,tempbuff, ivalue );//拷贝包体数据