应用层自定义的命令包
#pragma pack(1)
typedef struct _tagRecvType
{
int nLength;  //当前包的总长度
BYTE Tag; //标记,值为0X55
BYTE Command;  //自定义的应用层协议,为0X01的时候是登陆,0X02的时候为传送数据
char chContent[1024]; //数据内容
}RecvType;
#pragma pack()然后是对客户端的消息处理:
int nRet = 0; //每次接收到的数据的长度
int nPackageLength = 0; //当前收到的包的长度
int nRest = MAX_BUFFER_SIZE; //收到一个完整的包还差的字节
int nRecvLength = 0; //当前收到的字节数
char buf[MAX_BUFFER_SIZE+1] = {0}; //接收数据缓存
CWSocket wsk;
wsk = s;

while(1)
{
info.Empty();
//接收数据,一次收一个完整的数据包
while(nRest > 0)
{
nRet = wsk.ReadData(buf+nRecvLength, nRest, 60);
nRecvLength += nRet;
char* pTemp = strchr(buf, 0x55);
int nTemp = pTemp - buf;
char chTemp[8] = {0};
strncpy(chTemp, buf, nTemp);
nPackageLength = atoi(chTemp);
nRest = nPackageLength - nRet;
}
buf[nPackageLength] = '\0';
RecvType* pRecvType = (RecvType*)buf;

if(pRecvType->Command == 0x01) //登陆
{

}
if(pRecvType->Command == 0x02) //发送数据
{

}
}首先想请大家帮我看看,这样写,功能是否实现,还有就是哪里写得不好希望大家指出来,能帮我改一下更好了,谢谢了。

解决方案 »

  1.   

    功能是否实现只有你自己调试了才知道。客户端的消息处理: 如果你是对话框下写的这段代码,while(1) 就会引起界面卡死
      

  2.   

    提供的代码太少,很难系统的说。类也没公布。代码不全。只能指明几点。
    首先char    chContent[1024]; //数据内容
    从你定义的协议来看,你是定长的数据包,就没必要用标记。
    从我理解的你的CWSocket类来些点代码吧。
    while(1)
        {
            info.Empty();
            //接收数据,一次收一个完整的数据包
             nRet = wsk.ReadData(buf, MAX_BUFFER_SIZE, 60);
    //60应该是不超时,nRet 是返回接收到的实际数据包大小吧。还有我认为接收数据包的缓存要在wsk内去实现
             
            
            
            if(nRet >= sizeof(RecvType))
            {
               RecvType* pRecvType = (RecvType*)buf;
            
              if(pRecvType->Command == 0x01) //登陆
                 {
                
               }
              if(pRecvType->Command == 0x02) //发送数据
               {
                
               }
               
               //这里还要去wsk减去sizeof(RecvType)大小的缓存,因为这里处理了一个数据包。
             }
    }
      

  3.   


    帖一下类里面的代码:
    int CWSocket::ReadData(char FAR* buf, int len, int timeout)
    {
    if(!m_bConnected || m_sSocket == NULL)
    {
    err = -1;
    return -1;
    } HANDLE hThread;
    DWORD dwThreadId;
    TPARA para; para.OutTime = timeout;
    para.s = m_sSocket;
    para.bExit = FALSE;
    para.IsExit = FALSE;
    para.pbConnected = &m_bConnected;
    hThread = CreateThread(NULL, NULL, TimeoutControl, (LPVOID)(&para), 0, &dwThreadId);
    if (hThread == NULL) return -1; int nRet = recv(m_sSocket, buf, len, 0);
    if(nRet == SOCKET_ERROR) err = WSAGetLastError(); para.bExit = TRUE;
    while(!para.IsExit) Sleep(1); return nRet;
    }这个类是别人写的,如果客户端发送包的时候,chContent里只写了少数几个字符,那么接收到的也是1024字节长的数据么?不太清楚这个,就弄了个标记。
      

  4.   

    不知道TimeoutControl这个线程做什么。从这里看来没做缓存。
    一般来讲你这个数据包才1k多点,一般不会粘包。
    为了万一可以这么做。    int nRet = 0;                        //每次接收到的数据的长度
        int nPackageLength = sizeof(RecvType);   //一个包的长度
        int nRest = MAX_BUFFER_SIZE;        //收到一个完整的包还差的字节
        int nRecvLength = 0;                //当前收到的字节数
        char buf[MAX_BUFFER_SIZE*10] = {0};    //数据缓冲区
        CWSocket wsk;
        wsk = s;
        
        while(1)
        {
            info.Empty();
            //接收数据,一次收一个完整的数据包
             nRet = wsk.ReadData(buf+nRecvLength, MAX_BUFFER_SIZE, 60);
            nRecvLength += nRet;
            buf[nRecvLength] = '\0';
            
            if(nRecvLength >= nPackageLength)
            {
               RecvType* pRecvType = (RecvType*)buf; 
            
              if(pRecvType->Command == 0x01) //登陆 
                { 
                
              } 
              if(pRecvType->Command == 0x02) //发送数据 
                { 
                
              } 
              nRecvLength  -= nPackageLength;
              memmove(buf,buf + nPackageLength,nRecvLength);
            }
             
         sleep(15);
         }
      

  5.   

    你这个代码,我怕TCP拼包,然后接收到别的包的数据奉上超时的代码:
    DWORD CALLBACK CWSocket::TimeoutControl(LPVOID lpParm)
    {
    TPARA* para = (TPARA*)lpParm;
    time_t stime = time(NULL);
    BOOL bTimeover = FALSE; while(!bTimeover)
    {
    if(para->bExit)
    {
    para->IsExit = TRUE;
    return 0;
    } Sleep(1); time_t ntime = time(NULL);
    if((ntime - stime) > para->OutTime) bTimeover = TRUE;
    } if(para->bExit)
    {
    para->IsExit = TRUE;
    return 0;
    } if(para->s != NULL)
    {
    para->pbConnected[0] = FALSE;
    shutdown(para->s, SD_RECEIVE);
    Sleep(5);
    closesocket(para->s);
    } para->IsExit = TRUE;
    return 0;
    }