开发者

Concatenating strings into own protocol

I'm writing networking programming using socket.h to my studies. I have written server and client simple programs that can transfer files between them using buffer size given by user.

Server

    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);
    }

}

Client

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();
    }

The problem occurs, when I want to implement my own protocol- two chars (control), 32 chars hash, and the rest of package is data. I tried few times to split it and I end up with this code:

Server

#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);
    }

}

Client

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();
    }

But this one inputs to file some ^@ instead of real data. Displaying "data" to console looks the same on server and client. If you know how I can split it up, I would be very grateful.


You have some issues which may or may not be your problem.

(1) send/recv can return less than you requested. You may ask to receive 30 bytes but only get 10 on the recv call so all of these have to be coded in loops and buffered somewhere until you actually get the number you wanted. Your first set of programs was lucky to work in this regard and probably only because you tested on a limited amount of data. Once you start to push through more data your assumptions on what you are reading (and comparing) will fail.

(2) There is no need to keep allocating char buffers in the loops; allocate them before the loop or just use a local buffer rather than the heap. What you are doing is inefficient and in the second program you have memory leaks because you don't delete them.

(3) You can get rid of the strcpy/strncpy statements and just use memmove()

Your specific problem is not jumping out at me but maybe this will push in the right direction. More information what is being transmitted properly and exactly where in the data you are seeing problems would be helpful.


But this one inputs to file some ^@ instead of real data. Displaying "data" to console looks the same on server and client. If you know how I can split it up, I would be very grateful.

You say that the data (I presume the complete file rather than the '^@') is the same on both client and server? If this is the case, then your issue is likely writing the data to file, rather than the actual transmission of the data itself.

If this is the case, you'll probably want to check assumptions about how the program writes to file - for example, are you passing in text data to be written to file, or binary data? If you're writing binary data, but it uses the NULL-terminated string, chances are it will quit early treating valid binary information as a NULL.

If it's text mode, you might want to consider initialising all strings with memset to a default character (other than NULL) to see if it's garbage data being out put.

If both server and client display the '^@' (or whatever data), binary based char data would be incompatible with the strcpy/strcat functions as this rely on NULL termination (where-as binary uses size termination instead).

I can't track down the specific problem, but maybe this might offer an insight or two that helps.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜