图像从winsock 中损坏

问题描述 投票:0回答:1

我正在C++上构建应用程序的通信模块,我使用Windows套接字建立连接并使用send()函数发送文件。 当我尝试发送图像时,它在服务器客户端中损坏,但是当我发送文本文件时,它工作正常。

我的应用程序分为客户端和服务器。我的客户端连接到服务器并将 png 文件存储到字符串变量(数据)中。在 512 个字节中的 512 个字节中,程序将包含图像的数组存储到“数据”中,并通过套接字发送::

//Stores the binary
int imgBinaryExtractor(){   
    int i = 0;
    
    
    std::ifstream file1;
    char ch; //Used to storde the image characters into img_binary
    const char* sfile = "original.png";

    file1.open(sfile, std::ios::binary);


while (file1.get(ch)) {

    
    img_binary[i] = ch; //Put the png data into the array
    file_size++; //Stores the size of the image
    i++; //Just a controller
    //std::cout << "\nCaractere atual no char: " << ch;
    //std::cout << "\nCaractere atual no aray: " << img_binary[i];
}

    file1.close();
    std::cout << "file_size: " << file_size << std::endl;

    int a = 512;
       
    while(controle_file_size <= a){
        //  data = data+img_binary[a];
    //  if(img_binary[a] != "\n"){
        
        data = data + img_binary[controle_file_size];
            controle_file_size++;
        //}
}
            a = controle_file_size + 512;       

        
return 0;
}



//Sends the image:
int data_send(std::string data){
    std::cout << "\nData send has been called";
            
              sent_message = "\nSending Image";
              send(client.socket, sent_message, strlen(sent_message), 0);                   
                            
                             sent_message = data.c_str();
                             send(client.socket, sent_message, strlen(sent_message), 0);
                                           
              sent_message = "\nThe image has been send";
              send(client.socket, sent_message, strlen(sent_message), 0); 
               

}

为了确保所有文件都已发送,我在 Int Main 上创建了此逻辑:


int main(){
    
    
    std::thread worker1(conectar, "127.0.0.1", "8080"); //COnnection thread
    
    
    std::cout << "\nPress any button to send the image";
    system("pause");
    
    std::thread worker2(data_send, data); //Data send
    
    while(controle_file_size < file_size){
        
    imgBinaryExtractor();
    std::cout << data;
    
        worker2.join(); //
}

    
    worker1.join();         
//  worker2.join(); 
    
    std::cout << "\nThe image has been sent" << std::endl;
}

在服务器代码中:

这会从客户端接收 512 个字节并将其存储到“binario”变量中:

while (1)
    {
        //memset(tempmsg, 0, DEFAULT_BUFLEN);

        if (new_client.socket != 0)
        {
            int iResult = recv(new_client.socket, tempmsg, DEFAULT_BUFLEN, 0);      
            
            std::cout << "\nSize of buffer is: " << strlen(tempmsg);
            if (iResult != SOCKET_ERROR)
            {
   
                if (strcmp("", tempmsg))
                    //msg = "PC filho #" + std::to_string(new_client.id) + ": " + tempmsg;
                    
                        std::cout << tempmsg;
                        
                        binario = tempmsg;
                        
                        
    binaryStorer(binario);

稍后它调用此函数将二进制文件存储到 png 文件中。

int binaryStorer(std::string binario){
    
    int i = 0;
    
    std::ofstream file2;
    const char* tfile = "passed-image.png";

    file2.open(tfile, std::ios::binary);


file2 << binario;
    file2.close();
    return 0;   
}
c++ sockets binaryfiles file-transfer data-transfer
1个回答
2
投票

这一点是错误的:

sent_message = data.c_str();
send(client.socket, sent_message, strlen(sent_message), 0);

data
是一个包含二进制数据的
std::string
,该二进制数据可能包含分散在各处的零值。然后,从
std::string
中获取原始数组并对其运行
strlen
- 该函数旨在用于 C 风格的以 null 结尾的文本字符串。

https://en.cppreference.com/w/cpp/string/byte/strlen

返回给定字节串的长度,即字节数 字符数组中的字符,其第一个元素指向 str 直到但不包括第一个空字符。

我希望我不必解释为什么这会产生不正确的结果。

此外,

strlen
通过一次循环一个字符来查找字符串的长度,这是愚蠢的,因为你手头已经有了长度。尝试这样的事情:

send(client.socket, data.c_str(), data.size(), 0);

编辑:每条评论:什么是 C 风格的以 null 结尾的文本字符串?

在 C 中,您通常将文本字符串保存在字符数组中,并通过

char*
访问它们,不幸的是,这些都不能告诉您它们保存/指向的文本有多长。因此,约定是所有文本字符串都以空 (
\0
) 字符终止。如果您创建一个字符串文字,然后在调试器中查看它,您可以看到这一点,例如“Hello”将显示为
'H','e','l','l','o','\0'

这也意味着所有处理 C 字符串的 C 函数都将采用这种类型的数据,特别是

strlen
将查看此数组:
a,b,c,\0,d,e,f\0
- 包含 8 个字节 - 并告诉您长度是 3 .

© www.soinside.com 2019 - 2024. All rights reserved.