如何通过tcp正确发送二进制文件

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

我一直在尝试通过 Windows 上的套接字连接发送 PNG 文件。 我可以发送文本文件 (UTF-8),但是当它是关于二进制文件(例如 .exe 或 .png)时,输出会损坏,就在存在空字符的位置。

此外,我使用

std::ios::binary
将文件内容视为二进制,但即便如此,它还是损坏了。

这是我的服务器代码:

int recv_msg(){

  std::fstream fp;

    char* recvbuf = new char[DEFAULT_BUFLEN];
  int recvbuflen = DEFAULT_BUFLEN;
    int iResult = 0;
      
      iResult = recv(new_client.socket, recvbuf, recvbuflen, 0);
  
      if (iResult > 0) {
          //printf("Bytes received: %d\n", iResult);
      }
      else if (iResult == 0){
      
          printf("Going forward...\n");
      }
  

  if (!fp) {
//eero
  }
  do {
      iResult = recv(new_client.socket, recvbuf, recvbuflen, 0);
      if (iResult > 0) {
          printf("Bytes received: %d\n", iResult);
          fp.write(recvbuf, iResult);
      }
      else if (iResult == 0)
      {
      
          printf("Connection closing...\n");
      }

  } while (iResult > 0);
  fp.close();
  
  
  std::ofstream file2;
  const char* tfile = "passed-image.png";

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


file2 << tempmsg;
    file2.close();
    return 0;     

}

这是我的客户代码:

int data_send(){
      std::fstream fp;
          char* sendbuf = new char[DEFAULT_BUFLEN];
          fp.open("original.png", std::ios::in | std::ios::binary);
          if (!fp) {
//erro    return 1;
          }
          while (!fp.eof()) {
              fp.read(sendbuf, DEFAULT_BUFLEN);
                              
              iResult = send(client.socket, sendbuf, fp.gcount(), 0);
              if (iResult == SOCKET_ERROR) {
//erro
              }
          }
          //printf("Bytes Sent: %ld\n", iResult);
          fp.close();

}
c++ sockets binaryfiles file-transfer windows-socket-api
1个回答
0
投票

如果有帮助,这是完整的代码:

服务器:

//need to put: 
// -lWs2_32 -lwsock32 -std=c++11 -std=gnu++11 
//at the compiler options

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<fstream>
#include <iostream>
#include <ws2tcpip.h>
#include <string>
#include <thread>
#include <vector>
#include <winsock2.h>




#pragma comment (lib, "Ws2_32.lib")

/*
#define IP_ADDRESS "127.0.0.1"
#define DEFAULT_PORT "8080"
*/
#define DEFAULT_BUFLEN 10000000 


const char OPTION_VALUE = 1;
const int MAX_CLIENTS = 5;

    

struct client_type
{
    int id; //ID INT
    SOCKET socket;
};

std::string binario = "";

char tempmsg[DEFAULT_BUFLEN];


int recv_msg();

client_type new_client;

int process_client(client_type &new_client, std::vector<client_type> &client_array, std::thread &thread)
{
    std::string msg = "";   

    //Sessão de conversa, chat ###################################################################################
    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)
            {
                
                
                recv_msg();
   
   /*
                if (strcmp("", tempmsg))
                    //msg = "PC filho #" + std::to_string(new_client.id) + ": " + tempmsg;
                    
                        std::cout << tempmsg;
                        
                        binario = tempmsg;
                        
                        
    binaryStorer(binario);
    */
                        
                        
                //std::cout << msg.c_str() << std::endl;
                
                //Send message to all pcs
                for (int i = 0; i < MAX_CLIENTS; i++)
                {
                    if (client_array[i].socket != INVALID_SOCKET)
                        if (new_client.id != i)
                            iResult = send(client_array[i].socket, msg.c_str(), strlen(msg.c_str()), 0);
                }
            }
            else
            {
                msg = "PC #" + std::to_string(new_client.id) + " has disconected";
                system("cls");
                std::cout << msg << std::endl;

                closesocket(new_client.socket);
                closesocket(client_array[new_client.id].socket);
                client_array[new_client.id].socket = INVALID_SOCKET;

                //Closing message
                for (int i = 0; i < MAX_CLIENTS; i++)
                {
                    if (client_array[i].socket != INVALID_SOCKET)
                        iResult = send(client_array[i].socket, msg.c_str(), strlen(msg.c_str()), 0);
                }

                break;
            }
        }
    } //End chat ###################################################################################

    thread.detach();

    return 0;
}







int conectar(const char* IP_ADDRESS, const char* DEFAULT_PORT)
{
    WSADATA wsaData;
    struct addrinfo hints;
    struct addrinfo *server = NULL;
    SOCKET server_socket = INVALID_SOCKET;
    std::string msg = "";
    std::vector<client_type> client(MAX_CLIENTS);
    int num_clients = 0;
    int temp_id = -1;
    std::thread my_thread[MAX_CLIENTS];

    //Senting winsock up
    std::cout << "Initializing winsock..." << std::endl;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    //SOme configuration
    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    //Configuração do servidor
    std::cout << "Doing server configuration..." << std::endl;
    getaddrinfo(static_cast<LPCTSTR>(IP_ADDRESS), DEFAULT_PORT, &hints, &server);

    //Creating socket
    std::cout << "Creating socket..." << std::endl;
    server_socket = socket(server->ai_family, server->ai_socktype, server->ai_protocol);

    //Socket configuration
    setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &OPTION_VALUE, sizeof(int)); //Make it possible to re-bind to a port that was used within the last 2 minutes
    setsockopt(server_socket, IPPROTO_TCP, TCP_NODELAY, &OPTION_VALUE, sizeof(int)); //Used for interactive programs

    //Addressing
    std::cout << "Vinculation..." << std::endl;
    bind(server_socket, server->ai_addr, (int)server->ai_addrlen);

    //LIstening
    std::cout << "Waiting for conections..." << std::endl;
    listen(server_socket, SOMAXCONN);

    //ID function
    for (int i = 0; i < MAX_CLIENTS; i++)
    {
        client[i] = { -1, INVALID_SOCKET };
    }

    while (1)
    {

        SOCKET incoming = INVALID_SOCKET;
        incoming = accept(server_socket, NULL, NULL);


        
        if (incoming == INVALID_SOCKET) continue;
        num_clients = -1;


        temp_id = -1;
       



        for (int i = 0; i < MAX_CLIENTS; i++) 

        {
            if (client[i].socket == INVALID_SOCKET && temp_id == -1) 
            {
                client[i].socket = incoming;
                client[i].id = i;
                temp_id = i;
            }

            if (client[i].socket != INVALID_SOCKET) 
                num_clients++;

            //std::cout << client[i].socket << std::endl; //Tirar do comentario para inofrmar o ultimo pc rescentemente conectado
        }



        if (temp_id != -1)
        {
        //Send ID
            std::cout << "PC #" << client[temp_id].id << " Join" << std::endl;
            msg = std::to_string(client[temp_id].id);
            send(client[temp_id].socket, msg.c_str(), strlen(msg.c_str()), 0);

            //Creates process
            my_thread[temp_id] = std::thread(process_client, std::ref(client[temp_id]), std::ref(client), std::ref(my_thread[temp_id]));
        }
        else
        {
            msg = "Server full";
            send(incoming, msg.c_str(), strlen(msg.c_str()), 0);
            std::cout << msg << std::endl;
        }
    } //COnection loop



    closesocket(server_socket);

    for (int i = 0; i < MAX_CLIENTS; i++)
    {
        my_thread[i].detach();
        closesocket(client[i].socket);
    }


    WSACleanup();
    std::cout << "Finished" << std::endl;

    system("pause");
    return 0;
}   


int recv_msg(){

    std::fstream fp;

    char* recvbuf = new char[DEFAULT_BUFLEN];
    int recvbuflen = DEFAULT_BUFLEN;
    int iResult = 0;
        
        iResult = recv(new_client.socket, recvbuf, recvbuflen, 0);
    
        if (iResult > 0) {
            //printf("Bytes received: %d\n", iResult);
        }
        else if (iResult == 0){
        
            printf("Going forward...\n");
        }
    

    if (!fp) {
//eero
    }
    do {
        iResult = recv(new_client.socket, recvbuf, recvbuflen, 0);
        if (iResult > 0) {
            printf("Bytes received: %d\n", iResult);
            fp.write(recvbuf, iResult);
        }
        else if (iResult == 0)
        {
        
            printf("Connection closing...\n");
        }

    } while (iResult > 0);
    fp.close();
    
    
    std::ofstream file2;
    const char* tfile = "passed-image.png";

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


file2 << tempmsg;
    file2.close();
    return 0;       

}



int main(){
    conectar("127.0.0.1", "8080");
    
}

客户:

//need to put: 
// -lWs2_32 -lwsock32 -std=c++11 -std=gnu++11 
//at the compiler options

#include<iostream>
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<fstream>
#include <string>
#include <thread>
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>



#define DEFAULT_BUFLEN 10000000 
#pragma comment (lib, "Ws2_32.lib") 

struct client_type
{
    SOCKET socket;
    int id;
    char received_message[DEFAULT_BUFLEN];
};


//#########################################
//Global
const char* sent_message = "";  //Will contain the code of the image
int iResult = 0;
client_type client = { INVALID_SOCKET, -1, "" };
const char* message;        
std::string data = ""; //Will contain the binary of the image
int file_size = 0; //will contain the size of the image
int controle_file_size = 0; //Just for a loop
//#########################################




int conectar(const char* ip, const char* porta)
{



    WSAData wsa_data;
       struct addrinfo *result = NULL, *ptr = NULL, hints;       
       

       // winsock start
       iResult = WSAStartup(MAKEWORD(2, 2), &wsa_data);
       if (iResult != 0) {
           std::cout << "WSAStartup() has failed: " << iResult << std::endl;
           return 1;
       }

       ZeroMemory(&hints, sizeof(hints));
       hints.ai_family = AF_UNSPEC;
       hints.ai_socktype = SOCK_STREAM;
       hints.ai_protocol = IPPROTO_TCP;

       std::cout << "Conncecting...\n";

       // Transform IP and Pot to a usable format
       iResult = getaddrinfo(static_cast<LPCTSTR>(ip), porta, &hints, &result);
       if (iResult != 0) {
           std::cout << "getaddrinfo() failed: " << iResult << std::endl;
           WSACleanup();
           //system("pause");
           return 1;
       }

       for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {

           // Creates socket
           client.socket = socket(ptr->ai_family, ptr->ai_socktype,
               ptr->ai_protocol);
           if (client.socket == INVALID_SOCKET) {
               std::cout << "socket() failed " << WSAGetLastError() << std::endl;
               WSACleanup();
              // system("pause");
               return 1;
           }

           // Connects do server
           iResult = connect(client.socket, ptr->ai_addr, (int)ptr->ai_addrlen);
           if (iResult == SOCKET_ERROR) {
               closesocket(client.socket);
               client.socket = INVALID_SOCKET;
               continue;
           }
           break;
       }

       freeaddrinfo(result);

       if (client.socket == INVALID_SOCKET) {
           std::cout << "Is the server on?" << std::endl;


           //Messagebox

           WSACleanup();

           return 1;
       }

       std::cout << "Conected to server" << std::endl;

       //Recives ID
       recv(client.socket, client.received_message, DEFAULT_BUFLEN, 0);



           client.id = atoi(client.received_message);

           //Send message
           bool conectado = true;
           
           while(conectado == true){
           }          
           system("pause"); 

       return 0;

    
}



int data_send(){
        std::fstream fp;
            char* sendbuf = new char[DEFAULT_BUFLEN];
            fp.open("original.png", std::ios::in | std::ios::binary);
            if (!fp) {
//erro  return 1;
            }
            while (!fp.eof()) {
                fp.read(sendbuf, DEFAULT_BUFLEN);
                                
                iResult = send(client.socket, sendbuf, fp.gcount(), 0);
                if (iResult == SOCKET_ERROR) {
//erro
                }
            }
            //printf("Bytes Sent: %ld\n", iResult);
            fp.close();

}




int main(){
    
    
    //Thread para conectar:
    std::thread worker1(conectar, "127.0.0.1", "8080"); 
    
        
    //Para iniciar a transferencia:
    system("pause");    

        
    
    std::thread worker2(data_send); //Data send


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


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