我正在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;
}
这一点是错误的:
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 .