ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

c-如何提取消息的长度信息,并仅从TCP字节流中提取那么多的消息?

2019-10-11 20:05:19  阅读:194  来源: 互联网

标签:winsock c tcp networking


我正在尝试通过c中的Socket发送消息.我已经阅读了很多与此有关的堆栈溢出问题,但仍无法弄清楚它是如何工作的.可以说我正在向本地主机服务器发送以下字符(M,a,r,t,i,n),人们建议您可以使用4个字节作为长度(即32位),以便它可以处理一条消息到4GB的长度).

我在客户端做了同样的事情,但仍然不知道如何在服务器端解决这个问题,是我只想接收开始的3个字节(M,a,r)还是最后接收的3个字节(t,i,n)我的数据.

我在发布我的代码,请主要在服务器端帮助我,如果能写一些与代码相关的代码会很感激.

           Client side code
std::vector<char> userbuffer(20);
std::cout<<"\nclient:"<<std::endl;
    char* p = userbuffer.data();
    *p = 'M';
            ++p; *p = 'a';
            ++p; *p = 'r';
            ++p; *p = 't';
            ++p; *p = 'i'; 
            ++p; *p = 'n';
            size_t length = strlen(userbuffer.data());
    uint32_t nlength = htonl(length);
            //line containg message length information
           int header_info = send(socketFD, (char*)&nlength, 4, 0); 
           // Data bytes send to the server
    int bytes_sent = send(socketFD, userbuffer.data(), length, 0);

    if(bytes_sent == SOCKET_ERROR){ //some errror handling}





 Server Side Code
 char receivebuffer[MAX_DATA] = { '\0' };
 int bytesReceivedFromClientMsg = 1;
 int length_bytes = 0;
 uint32_t length, nlength;
 //code to check length if we have received whole data length
 while(length_bytes < 4){
 int read = recv(clientSocket, ((char*)&nlength)+length_bytes, (4-length_bytes), 0);
 if (read == -1) { //error handling}
 length_bytes += read;}
// Most painfull section to understand.
// I implemented this code from some ideas on internet 
//but still cant find how its extracting length and what i am reading :(
       while(bytesReceivedFromClientMsg > 0){
    int msgheader = recv(clientSocket,(char*)&nlength,6, 0);
    length = ntohl(nlength);//leng value here is in severel thousand size
    char *receivebuffer = new char(length+1);
        bytesReceivedFromClientMsg = recv(clientSocket, receivebuffer, msgheader, 0);
    receivebuffer[length] = 0 ;
    std::cout<<"msg header is :"<<msgheader<<std::endl;
    std::cout<<"msg data is :"<<bytesReceivedFromClientMsg<<std::endl;

        if(bytesReceivedFromClientMsg == SOCKET_ERROR){//some error handling}

解决方法:

您需要为您的网络协议设计.有些协议(如SMTP)是类似文本的协议.您必须阅读字符,直到在类似文本的协议中找到换行符为止.

使用基于消息的协议,您就有更好的机会选择高性能协议.您定义一个标头(在代码中使用但未定义).在标题中,您可以输入有关长度的信息,也可以包含有关下一条消息的类型的信息.然后,您将标题发送到邮件正文的前面.在您的示例中,主体为“马丁”.

接收者的状态为“已收到标头”.如果没有收到完整的标头(或根本没有标头),它将使用标头的大小作为块大小.它接收chunksize字节到头变量中.接收到标头完成后,接收器将块大小设置为标头中设置的大小,并向有效负载缓冲区接收这么多字节.完成此操作后,状态“已收到标头”再次变为false.

int receive(socket sock, char * buffer, int chunk_size)
{
    int offset = 0;

    while (chunk_size > 0)
    {
        // add select() here when you have a non-blocking socket.
        int n = recv(sock, buffer+offset, chunk_size);
        // TODO: error handling
        offset += n;
        chunk_size -= n;
    }

    // return amount of received bytes
    return offset;
}

void do_receive(void)
{
    struct {
        int size;
        // other message information
    } header;

    while (true)
    {
        receive(sock, &header, sizeof(header);
        receive(sock, buffer, header.size);
        process_message(buffer, header.size);
    }
}

上面的代码不会通过任何编译器.但这说明了主意.

标签:winsock,c,tcp,networking
来源: https://codeday.me/bug/20191011/1895145.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有