gpt4 book ai didi

c++ - 读取整个文件并通过套接字发送

转载 作者:搜寻专家 更新时间:2023-10-31 01:11:13 27 4
gpt4 key购买 nike

我做了一个应该传输文件的服务器和客户端。我试图让它读取整个文件并发送。但现在我看到了,我遇到了问题。服务器应在客户端连接时自动发送文件。但是文件是空的,不知道问题出在哪里您可以看到我正在尝试发送 .txt 文件。但我希望以后发送一个大文件,但不超过 1MB。)

编辑:

图片在这里:http://img819.imageshack.us/img819/8259/aadi.jpg

  • 左侧:我尝试发送的文件。
  • 右侧:我收到的文件

enter image description here

问题:我收到的文件已经损坏,无法使用。

服务器:

#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;

#pragma comment(lib, "Ws2_32.lib")
#define Port 6000

SOCKET Socket, Sub;
WSADATA Winsock;
sockaddr_in Addr;
sockaddr_in IncomingAddress;
int AddressLen = sizeof(IncomingAddress);

int main()
{
WSAStartup(MAKEWORD(2, 2), &Winsock); // Start Winsock

if(LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2) // Check version
{
WSACleanup();
return 0;
}

Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

ZeroMemory(&Addr, sizeof(Addr));
Addr.sin_family = AF_INET;
Addr.sin_port = htons(Port);
bind(Socket, (sockaddr*)&Addr, sizeof(Addr));

if(listen(Socket, 1) == SOCKET_ERROR)
{
printf("listening error\n");
}
else
{
printf("listening ok\n");
}

if(Sub = accept(Socket, (sockaddr*)&IncomingAddress, &AddressLen))
{
char *ClientIP = inet_ntoa(IncomingAddress.sin_addr);
int ClientPort = ntohs(IncomingAddress.sin_port);
printf("Client conncted!\n");
printf("IP: %s:%d\n", ClientIP, ClientPort);

printf("Sending file .. \n");

FILE *File;
char *Buffer;
unsigned long Size;

File = fopen("C:\\Prog.rar", "rb");
if(!File)
{
printf("Error while readaing the file\n");
getchar();
return 0;
}

fseek(File, 0, SEEK_END);
Size = ftell(File);
fseek(File, 0, SEEK_SET);

Buffer = new char[Size];

fread(Buffer, Size, 1, File);
char cSize[MAX_PATH];
sprintf(cSize, "%i", Size);

fclose(File);
send(Sub, cSize, MAX_PATH, 0); // File size

//int len = Size;
//char *data = Buffer;

int Offset = 0;
while(Size > Offset)
{
int Amount = send(Sub, Buffer + Offset, Size - Offset, 0);

if(Amount <= 0)
{
cout << "Error: " << WSAGetLastError() << endl;
break;
}
else
{
Offset += Amount;
printf("2\n");
}
}


free(Buffer);
closesocket(Sub);
closesocket(Socket);
WSACleanup();
}

getchar();
return 0;
}

客户:

#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;

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

SOCKET Socket;
WSADATA Winsock;
sockaddr_in Addr;
int Addrlen = sizeof(Addr);

int main()
{
WSAStartup(MAKEWORD(2, 2), &Winsock); // Start Winsock

if(LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2) // Check version
{
WSACleanup();
return 0;
}

Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

ZeroMemory(&Addr, sizeof(Addr)); // clear the struct
Addr.sin_family = AF_INET; // set the address family
Addr.sin_addr.s_addr = inet_addr("127.0.0.1");
Addr.sin_port = htons(6000); // set the port

if(connect(Socket, (sockaddr*)&Addr, sizeof(Addr)) < 0)
{
printf("Connection failed !\n");
getchar();
return 0;
}

printf("Connection successful !\n");

printf("Receiving file .. \n");



int Size;
char *Filesize = new char[1024];

if(recv(Socket, Filesize, 1024, 0)) // File size
{
Size = atoi((const char*)Filesize);
printf("File size: %d\n", Size);
}

char *Buffer = new char[Size];

//int len = Size;
//char *data = Buffer;

int Offset = 0;
while(Size > Offset)
{
int Amount = recv(Socket, Buffer + Offset, Size - Offset, 0);

if(Amount <= 0)
{
cout << "Error: " << WSAGetLastError() << endl;
break;
}
else
{
Offset += Amount;
printf("2\n");
}
}

FILE *File;
File = fopen("Prog.rar", "wb");
fwrite(Buffer, 1, Size, File);
fclose(File);

getchar();
closesocket(Socket);
WSACleanup();
return 0;
}

最佳答案

send API 可能无法发送您请求发送的所有数据。所以,你要注意返回值,从上次发送结束的地方重试发送。例如:

offset = 0;
while (offset < bufsize) {
r = send(socket, buf+offset, bufsize-offset);
if (r <= 0) break;
offset += r;
}

虽然您正在为文件传输做类似的事情,但您不确定文件大小是否属于这种情况。

发送文件大小时,只需要发送代表大小的字符串即可,不需要发送整个MAX_PATH。然后接收方需要解析第一个字符串以确定大小,但是在第一个字符串结束后读入的任何数据都需要被视为文件的一部分。但是,由于您正在尝试发送 MAX_PATH,接收方应该收到相同的数量。您的客户端代码收到 1024 字节,但没有迹象表明这与 MAX_PATH 大小相同。

recv API 返回的字节数也可能少于请求的字节数。您使用循环来处理读取文件,但您可能需要一个循环来读取包含文件大小的整个消息。

在您的客户端接收循环中,您正在递增 data 指针。这使得以后无法写出该文件。不过,您已经有了 Buffer,因此请使用它来写出您的文件。

fwrite(Buffer, 1, len, File);

如果您在执行套接字 I/O 时遇到错误,您可以使用 WSAGetLastError() 检索错误,或者您可以在套接字上发出 getsockopt() SO_ERROR 选项。这些可能返回不同的值,但错误原因应该是相关的。

关于c++ - 读取整个文件并通过套接字发送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15176213/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com