通过TCP/IP发送文件
Sending files via TCP/IP
我正在尝试使用windows上的C++程序通过TCP/IP发送文件。发送和接收工作正常。但是在接收到的文件中,每40个字符后出现两个逗号。例如,如果我发送:
123456789
123456789
123456789
123456789
123456789
123456789
23456789
123456789
123456789
123456789
123456789
123456789
123456789
123456789
接收的文件是:
123456789
123456789
123456789
123456789
123456789
„123456789
123456789
123456789
123456789
123456789
„123456789
123456789
123456789
123456789
以下是发送文件的服务器代码:
static int send_client_file(SOCKET sock, char *Sbuffer){
int n = 0;
char* f_name = "send.txt";
//char* f_name = "server.c";
cout << endl << "Waiting for the client message" << endl;
FILE *fp = fopen(f_name, "r");
if (fp == NULL)
{
cout << "ERROR : File " << f_name << " not found ";
perror("fopen()");
exit(errno);
}
//bzero(Sbuffer, 50); // on vide le buffer d'envoie
memset(Sbuffer, 0, 50);
while((n = fread(Sbuffer, sizeof(char), 50, fp)) > 0)
{
if((n = send(sock, Sbuffer, strlen(Sbuffer), 0)) < 0)
{
perror("send()");
exit(errno);
}
memset(Sbuffer, 0, 50);
}
cout << "file sent" << endl;
return n;
}
这里是接收它的客户端代码:
int static recv_server_file(SOCKET sock, char *buffer){
int n = 0;
int m = 0;
cout << endl << "Receiving file from the server..." << endl;
char* f_name = "receive.txt";
FILE *fp = fopen(f_name, "a");
if (fp == NULL)
{
cout << "ERROR : File " << f_name << "not found " << endl;
perror("fopen()");
exit(errno);
}
else {
while(n = recv(sock, buffer, Rbuffer_size, 0))
{
if (n < 0)
{
perror("recv()");
exit(errno);
}
m = fwrite(buffer, sizeof(char), n, fp);
if(m < n)
{
cout << "File write failed." << endl;
break;
}
break;
memset(buffer, '/0', Rbuffer_size);
}
cout << "ok!" << endl;
fclose(fp);
}
cout << "The received data is : " << buffer << endl ;
return m;
}
正如您所看到的,在接收的文件中出现了","。知道如何解决这个问题吗?
从表面上看,缓冲区溢出了。请注意,不需要的字符出现在50个字节之后(而不是您在问题中所说的40个)。您的缓冲区有50个字符长。
您不能对已读入的缓冲区调用strlen(),因为strlen需要一个终止的null字符才能工作。也就是说,您需要缓冲区为51个字符。
这可能不是唯一的问题,但它肯定是其中的一部分
这里有很多问题。
以下是发送文件的服务器代码:
static int send_client_file(SOCKET sock, char *Sbuffer){
int n = 0;
char* f_name = "send.txt";
//char* f_name = "server.c";
cout << endl << "Waiting for the client message" << endl;
FILE *fp = fopen(f_name, "r");
if (fp == NULL)
{
cout << "ERROR : File " << f_name << " not found ";
perror("fopen()");
exit(errno);
}
//bzero(Sbuffer, 50); // on vide le buffer d'envoie
memset(Sbuffer, 0, 50);
不必要。去除
while((n = fread(Sbuffer, sizeof(char), 50, fp)) > 0)
{
if((n = send(sock, Sbuffer, strlen(Sbuffer), 0)) < 0)
其中的send()
部分应该是send(sock, Sbuffer, n, 0)
。这就是根本问题。你发送的长度不对。您还假设刚刚读取的数据实际上包含一个null,对此无法保证。strlen()
调用可能会溢出缓冲区并导致未定义的行为。
{
perror("send()");
exit(errno);
}
memset(Sbuffer, 0, 50);
memset()
是不必要的。去除
}
cout << "file sent" << endl;
return n;
}
给你零分。我看不出有什么意义。
这里是接收它的客户端代码:
int static recv_server_file(SOCKET sock, char *buffer){
int n = 0;
int m = 0;
cout << endl << "Receiving file from the server..." << endl;
char* f_name = "receive.txt";
FILE *fp = fopen(f_name, "a");
if (fp == NULL)
{
cout << "ERROR : File " << f_name << "not found " << endl;
perror("fopen()");
exit(errno);
}
else {
while(n = recv(sock, buffer, Rbuffer_size, 0))
{
if (n < 0)
{
perror("recv()");
exit(errno);
}
m = fwrite(buffer, sizeof(char), n, fp);
if(m < n)
{
cout << "File write failed." << endl;
break;
}
break;
memset(buffer, '/0', Rbuffer_size);
同样,memset()
是不必要的:删除。
}
在您的客户端代码中,缓冲区实际上从未设置过memsette。这可能就是问题所在。
第一次迭代假定"buffer"已设置为"\0",而且此代码是多余的
if (n < 0)
{
perror("recv()");
exit(errno);
}
由于while(…)已经检查了这一点,在迭代结束时,您可以在memset之前中断循环,并通过这样做使整个循环变得冗余。请做记忆集,排除那些可能的罪魁祸首,你也可以应用这些建议,但这取决于你。
编辑:通过使循环成为冗余,您可能无法接收到所有数据。
编辑#2:此外,您将忽略"send"的返回值。从msdn页面:
如果没有发生错误,send将返回发送的字节总数,该总数可以小于len参数中请求发送的字节数。否则,将返回SOCKET_ERROR值,并且可以通过调用WSAGetLastError来检索特定的错误代码。
因此,数据可能会被丢弃,因为无法保证它会立即发送所有数据。
编辑#3(很抱歉编辑过多)此外,您不会关闭服务器代码中的文件句柄
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 文本文件中的单词链表
- CMake-按正确顺序将项目与C运行时对象文件链接
- 使用新行和不使用新行读取文件
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 挂起和取消挂起一个文件DLL
- 如何确定我已使用非编码文件到达 EOF?
- 命名空间中具有.h和.cpp文件的类
- 如何从 boost::asio::ssl::stream<boost::asio::ip::tcp::socket> 获取本机套接字文件描述器?
- 从包含 IP 标头片段的二进制文件中读取结构的最佳方法是什么
- C++ - 使用代码块从文件中读取 IP 地址
- 通过C 中的TCP/IP协议发送.TXT文件
- TCP/IP文件传输C
- 如何在Windows上绕过主机文件获取真实的IP地址
- 将域的IP保存到TXT文件/将我的动态IP保存到带有C 或批处理的TXT文件中
- 获取 PCAP 文件中数据包的 IP 地址
- 运行.EXE文件时无法访问 IP 摄像机
- 如何从C++文件中读取二进制格式的 IP 地址
- 通过TCP/IP发送文件