将字符串连接到自己的协议中

Concatenating strings into own protocol

本文关键字:协议 自己的 字符串 连接      更新时间:2023-10-16

我正在用socket.h编写网络程序来学习。我已经编写了服务器和客户端简单的程序,可以使用用户指定的缓冲区大小在它们之间传输文件。

服务器

    void transfer(string name)
{
    char *data_to_send;
    ifstream myFile;
    myFile.open(name.c_str(),ios::binary);
    if(myFile.is_open))
    {
        while(myFile.eof))
        {
            data_to_send = new char [buffer_size];
            myFile.read(data_to_send, buffer_size);
            send(data_to_send,buffer_size);
            delete [] data_to_send;
        }
        myFile.close();
        send("03endtransmission",buffer_size);
    }
    else
    {
        send("03error",buffer_size);
    }
}
客户

void download(string name)
{
    char *received_data;
    fstream myFile;
    myFile.open(name.c_str(),ios::out|ios::binary);
    if(myFile.is_open()) 
    {
        while(1)
        {
            received_data = new char[rozmiar_bufora];
            if((receivedB = recv(sockfd, received_data, buffer_size,0)) == -1) {
                perror("recv");
                close(sockfd);
                exit(1);
            }
            if(strcmp(received_data,"03endoftransmission") == 0)
            {
                cout<<"End of transmission"<<endl;
                break;
            }
            else if (strcmp(received_data,"03error") == 0)
            {
                cout<<"Error"<<endl;
                break;
            }
            myFile.write(received_data,buffer_size);
        }
        myFile.close();
    }

问题发生了,当我想实现我自己的协议-两个字符(控制),32个字符哈希,其余的包是数据。我尝试了几次将其分割,最后得到以下代码:

服务器

#define PAYLOAD 34
void transfer(string name)
{
    char hash[] = "12345678901234567890123456789012"; //32 chars
    char *data_to_send;
    ifstream myFile;
    myFile.open(name.c_str(),ios::binary);
    if(myFile.is_open))
    {
        while(myFile.eof))
        {
            data_to_send = new char [buffer_size-PAYLOAD];
            myFile.read(data_to_send, buffer_size-PAYLOAD);
            concatenation = new char[buffer_size];
            strcpy(concatenation,"02");
            strcat(concatenation,hash);
            strcat(concatenation,data_to_send);
            send(concatenation,buffer_size);
            delete [] data_to_send;
            delete [] concatenation;
        }
        myFile.close();
        send("03endtransmission",buffer_size);
    }
    else
    {
        send("03error",buffer_size);
    }
}
客户

void download(string name)
{
    char *received_data;
    fstream myFile;
    myFile.open(name.c_str(),ios::out|ios::binary);
    if(myFile.is_open()) 
    {
        while(1)
        {
            received_data = new char[buffer_size];
            if((receivedB = recv(sockfd, received_data, buffer_size,0)) == -1) {
                perror("recv");
                close(sockfd);
                exit(1);
            }
            if(strcmp(received_data,"03endoftransmission") == 0)
            {
                cout<<"End of transmission"<<endl;
                break;
            }
            else if (strcmp(received_data,"03error") == 0)
            {
                cout<<"Error"<<endl;
                break;
            }
            control = new char[3];
            strcpy(control,"");
            strncpy(control, received_data,2);
            control[2]='';
            hash = new char[33];
            strcpy(hash,"");
            strncpy(hash,received_data+2,32);
            hash[32]='';
            data = new char[buffer_size-PAYLOAD+1];
            strcpy(data,"");
            strncpy(data,received_data+34,buffer_size-PAYLOAD);
            myFile.write(data,buffer_size-PAYLOAD);
        }
        myFile.close();
    }

但是这个输入文件一些^@而不是实际数据。在服务器和客户机上向控制台显示"数据"看起来是一样的。如果你知道怎么分的话,我会很感激的。

你有一些问题可能是你的问题,也可能不是。

(1) send/recv的返回值小于您的请求。你可能要求接收30个字节,但在recv调用中只得到10个字节,所以所有这些都必须在循环中编码并缓冲在某个地方,直到你真正得到你想要的数字。您的第一组程序在这方面很幸运,可能只是因为您在有限的数据上进行了测试。一旦你开始阅读更多的数据,你对你正在阅读(和比较)的假设就会失败。

(2)不需要在循环中一直分配char缓冲区;在循环之前分配它们,或者只使用本地缓冲区而不是堆。你所做的是低效的,在第二个程序中,你有内存泄漏,因为你没有删除它们。

(3)可以去掉strcpy/strncpy语句,只使用memmove()

你的具体问题不是跳到我,但也许这将推动正确的方向。更多的信息是什么被正确传输的,以及你在数据中看到问题的确切位置,将会有所帮助。

但是这个输入文件一些^@而不是实际数据。显示控制台的"data"在服务器和客户机上看起来是一样的。如果你知道怎么做我可以把它分开,我将非常感激。

你说数据(我假设是完整的文件,而不是'^@')在客户端和服务器上是相同的?如果是这种情况,那么您的问题可能是将数据写入文件,而不是数据本身的实际传输。

如果是这种情况,您可能需要检查有关程序如何写入文件的假设-例如,您是传入要写入文件的文本数据,还是二进制数据?如果您正在编写二进制数据,但它使用以NULL结尾的字符串,那么它很可能会提前停止将有效的二进制信息视为NULL。

如果是文本模式,您可能需要考虑将所有带有memset的字符串初始化为默认字符(而不是NULL),以查看它是否被输出为垃圾数据。

如果服务器和客户端都显示'^@'(或任何数据),基于二进制的char数据将与strcpy/strcat函数不兼容,因为这依赖于NULL终止(而-as二进制使用大小终止)。

我无法找到具体的问题,但也许这可以提供一两个有帮助的见解。