我一直在尝试通过 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(); }
如果有帮助,这是完整的代码:
服务器:
//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;
}