通过 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;
}
如您所见,接收文件中出现了“,”。知道如何解决这个问题吗?
在您的客户端代码中,缓冲区实际上从未被存储。这可能是问题所在。
第一次迭代假定 'buffer' 已经设置为 '\0' 而且此代码是多余的
if (n < 0)
{
perror("recv()");
exit(errno);
}
由于 while(...) 已经检查了这一点,并且在迭代结束时,您在 memset 之前跳出循环,并通过这样做使整个循环变得多余。请执行 memsets 以排除那些可能的罪魁祸首,您也可以应用这些建议,但这取决于您。
编辑:
通过使循环冗余,您可能无法接收到所有数据。
编辑#2:
您还忽略了 'send' 的 return 值。来自 msdn 页面:
If no error occurs, send returns the total number of bytes sent, which can be less than the number requested to be sent in the len parameter. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.
所以数据可能会被丢弃,因为不能保证它会立即发送所有数据。
编辑 #3
(对不起,很多编辑)
你也不要在服务器代码中关闭你的文件句柄
从表面上看,您似乎遇到了缓冲区溢出。请注意,不需要的字符出现在 50 个字节之后(不是您在问题中所说的 40 个)。您的缓冲区长度为 50 个字符。
您不能在已读入的缓冲区上调用 strlen(),因为 strlen 需要终止空字符才能工作。也就是说,您需要缓冲区为 51 个字符。
这可能不是唯一的问题,但肯定是其中的一部分。
这里有很多问题。
Here is the server code for sending a file:
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)
。这是根本问题。您发送的长度错误。您还假设刚刚读取的数据实际上包含一个空值,对此无法保证。 strlen()
调用可能会溢出缓冲区并导致未定义的行为。
{
perror("send()");
exit(errno);
}
memset(Sbuffer, 0, 50);
memset()
是不必要的。移除。
}
cout << "file sent" << endl;
return n;
}
这里你要返回零。我不明白这一点。
And here is the client code to receive it :
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()
是不必要的:删除。
}
我正尝试在 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;
}
如您所见,接收文件中出现了“,”。知道如何解决这个问题吗?
在您的客户端代码中,缓冲区实际上从未被存储。这可能是问题所在。
第一次迭代假定 'buffer' 已经设置为 '\0' 而且此代码是多余的
if (n < 0)
{
perror("recv()");
exit(errno);
}
由于 while(...) 已经检查了这一点,并且在迭代结束时,您在 memset 之前跳出循环,并通过这样做使整个循环变得多余。请执行 memsets 以排除那些可能的罪魁祸首,您也可以应用这些建议,但这取决于您。
编辑: 通过使循环冗余,您可能无法接收到所有数据。
编辑#2: 您还忽略了 'send' 的 return 值。来自 msdn 页面:
If no error occurs, send returns the total number of bytes sent, which can be less than the number requested to be sent in the len parameter. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.
所以数据可能会被丢弃,因为不能保证它会立即发送所有数据。
编辑 #3 (对不起,很多编辑) 你也不要在服务器代码中关闭你的文件句柄
从表面上看,您似乎遇到了缓冲区溢出。请注意,不需要的字符出现在 50 个字节之后(不是您在问题中所说的 40 个)。您的缓冲区长度为 50 个字符。
您不能在已读入的缓冲区上调用 strlen(),因为 strlen 需要终止空字符才能工作。也就是说,您需要缓冲区为 51 个字符。
这可能不是唯一的问题,但肯定是其中的一部分。
这里有很多问题。
Here is the server code for sending a file:
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)
。这是根本问题。您发送的长度错误。您还假设刚刚读取的数据实际上包含一个空值,对此无法保证。 strlen()
调用可能会溢出缓冲区并导致未定义的行为。
{
perror("send()");
exit(errno);
}
memset(Sbuffer, 0, 50);
memset()
是不必要的。移除。
}
cout << "file sent" << endl;
return n;
}
这里你要返回零。我不明白这一点。
And here is the client code to receive it :
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()
是不必要的:删除。
}