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

时间:2011-09-03 18:53:39

标签: c++ c linux network-programming

我正在使用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]='\0';
            hash = new char[33];
            strcpy(hash,"");
            strncpy(hash,received_data+2,32);
            hash[32]='\0';
            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();
    }

但是这个输入文件^ @而不是真实数据。向控制台显示“数据”在服务器和客户端上看起来相同。如果你知道我怎么能分开它,我将非常感激。

2 个答案:

答案 0 :(得分:2)

您有一些问题可能会或可能不是您的问题。

(1)send/recv的回报率低于您的要求。您可能会要求接收30个字节,但只能在recv调用中获得10个字节,因此所有这些都必须在循环中进行编码并在某处缓冲,直到您实际获得所需的数字。您的第一套程序很幸运能够在这方面工作,可能只是因为您测试了有限的数据。一旦你开始推动更多数据,你对你正在阅读(和比较)的假设就会失败。

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

(3)您可以删除strcpy / strncpy语句并使用memmove()

你的具体问题不是向我跳出来,但也许这会推动正确的方向。更多信息正确传输的内容以及您遇到问题的数据中的确切位置将会有所帮助。

答案 1 :(得分:1)

  

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

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

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

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

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

我无法追踪具体问题,但也许这可能提供一两个有用的见解。