问题描述
我想用 C++ 定期从客户端向服务器发送一个文件.说,每 10 秒.send.txt 是我想通过套接字发送到服务器的文件
send.txt 的前 10 秒包含123456".我通过添加 78910 11 12 来更改文件内容,使其变为123456 78910 11 12"
服务器应该在接下来的 10 秒内收到123456 78910 11 12".但问题是我收到的文件仍然是原始文件(123456),看起来从未改变.
这是我的客户端代码:
#include "stdafx.h"#include #include #include #include #include <chrono>#include #include SOCKET 客户端;WSADATA 温索克;sockaddr_in serverAddr ,地址;int Addrlen = sizeof(serverAddr);文件 *文件;无符号长尺寸;字符*缓冲;无效的开始客户端(){WSAStartup(MAKEWORD(2,2), &winsock);if(LOBYTE(winsock.wVersion) != 2 || HIBYTE(winsock.wVersion) != 2 ){WSACleanup();}clientsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr("127.0.0.1");addr.sin_port = htons(6091);连接(clientsock,(sockaddr*)&addr,sizeof(addr));printf("套接字已连接...\n");//准备文件File = fopen("B:\\send.txt","rb");如果(!文件){printf("",WSAGetLastError());}printf("文件打开正常!\n");fseek(文件,0,SEEK_END);大小 = ftell(文件);fseek(文件,0,SEEK_SET);字符 [10];sprintf(cisi, "%i",Size);发送(clientsock,cisi,10,0);//发送的文件大小/* Buffer = (char*) malloc (Size+1) ;fread(缓冲区,大小,1,文件);fclose(文件);发送(clientsock,缓冲区,大小,0);//文件二进制发送免费(缓冲区);printf("发送完毕...\n");*/}void timer_start(std::functionfunc, unsigned int interval) {std::thread([func, interval]() {而(真){功能();std::this_thread::sleep_for(std::chrono::milliseconds(interval));}}).分离();}无效发送(){File = fopen("B:\\send.txt","rb");fseek(文件,0,SEEK_END);大小 = ftell(文件);fseek(文件,0,SEEK_SET);printf("成功...\n");缓冲区 = (char*) malloc (Size+1) ;fread(缓冲区,大小,1,文件);fclose(文件);发送(clientsock,缓冲区,大小,0);//文件二进制发送免费(缓冲区);printf("发送完毕...\n");}int _tmain(int argc, _TCHAR* argv[]) {启动客户端();timer_start(发送,10000);同时(真);//发送();//睡眠(5000);系统(暂停");返回0;}
服务器代码是
#include "stdafx.h"#include #include #include #include <chrono>#include #include SOCKET servsocket、ClientAcc;WSAData winsock;sockaddr_in addr,incomingAddress;int addrlen = sizeof(sockaddr_in);int addresslen = sizeof(incomingAddress);char *Filesize = new char[10];整数大小 = 0;char *Buffer = new char[Size];文件 *文件;无效开始_p(){//套接字初始化WSAStartup(MAKEWORD(2,2), &winsock);//套接字检查if(LOBYTE(winsock.wVersion) !=2 || HIBYTE(winsock.wVersion) != 2 ) {WSACleanup();}servsocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);addr.sin_family = AF_INET;addr.sin_port = htons(6091);绑定(servsocket, (sockaddr*)&addr, sizeof(addr));听(服务套接字,5);ClientAcc = accept(servsocket, (sockaddr*)&incomingAddress, &addresslen);char *ClientIP = inet_ntoa(incomingAddress.sin_addr);int ClientPort = ntohs(incomingAddress.sin_port);printf("客户端已连接...\n");printf("IP : %s:%d\n", ClientIP, ClientPort);//接收文件大小recv(ClientAcc,Filesize,10,0);大小 = atoi((const char*)Filesize);printf("文件大小:%d\n",Size);}void timer_start(std::functionfunc, unsigned int interval){std::thread([func, interval]() {而(真){功能();std::this_thread::sleep_for(std::chrono::milliseconds(interval));}}).分离();}无效接收(){缓冲区 = (char*)malloc(Size+1);int file_dit, total_file = 0 ;而(total_file
输出是:
服务器:
客户端已连接... IP : 127.0.0.1 : 15425 文件大小 : 20 文件收到按任意键继续...
客户:
套接字已连接...文件打开正常!... 成功 ... 发送完成... 成功 ... 发送完毕 ... 成功 ... 发送完毕 ...成功……发送完毕……成功……发送完毕……
我用过这种方式
定期发送文件,但结果不是我想要的.
我希望你能帮助我.谢谢你.我真的很感谢你的帮助.
在关闭文件之前,文件的内容实际上不会写入磁盘.我认为您在添加文本时保持文件打开状态,您需要在客户端再次读取之前关闭它.
fclose(file);//这是内容写入磁盘的时间.
此外,您在发送文件后并没有关闭文件.
因此,每次对文件(句柄)执行操作时,都应该先关闭它,然后再启动另一个.
真正的错误一定是你一直在阅读char cisi[10]
,它只有10个空格,你只发送10个字符.send(clientsock,cisi,10,0);
换行:
//...字符 [10];//...发送(clientsock,cisi,10,0);
到:
//...char *cisi = new char[Size];//...发送(clientsock,cisi,大小,0);
关于服务器端代码:
recv(ClientAcc,Filesize,10,0);
使用上面的代码行,您总是会得到 10 个字符.但在这里你不知道有多少字符来自客户端.
对此的基本解决方案是首先发送该号码(在文件之前),这样您就知道要完成接收操作必须读取多少字符.
一个完整的解决方案涉及到一些协议的实现.或者使用更高级的库(例如 boost.Asio).
推荐:
使用 fstream 来管理文件.毕竟,您正在使用 C++ 进行编码.;D
I want to send a file periodically from client to server in C++.say, every 10 seconds. send.txt is the file that i want to send to server through socket
send.txt contains "123456" for the first 10 seconds.i change the file content by adding 78910 11 12 so it becomes "123456 78910 11 12"
the server should receive "123456 78910 11 12" for the next 10 seconds. but the problem is the file that i received is still the original one (123456) and look like it never changes.
#include "stdafx.h"
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#include <iostream>
#include <chrono>
#include <thread>
#include <functional>
SOCKET clientsock; WSADATA winsock; sockaddr_in serverAddr , addr; int Addrlen = sizeof(serverAddr); FILE *File; unsigned long Size; char
*Buffer;
void startClient() {
WSAStartup(MAKEWORD(2,2), &winsock);
if(LOBYTE(winsock.wVersion) != 2 || HIBYTE(winsock.wVersion) != 2 ){
WSACleanup();
}
clientsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_port = htons(6091);
connect(clientsock,(sockaddr*)&addr,sizeof(addr));
printf("socket connected... \n");
//preparing the file
File = fopen("B:\\send.txt","rb");
if(!File) {
printf("",WSAGetLastError()); }
printf("File open ok ! \n");
fseek(File,0,SEEK_END); Size = ftell(File); fseek(File,0,SEEK_SET);
char cisi[10]; sprintf(cisi, "%i",Size);
send(clientsock,cisi,10,0); // file size sent
/* Buffer = (char*) malloc (Size+1) ; fread(Buffer,Size,1,File); fclose(File);
send(clientsock,Buffer,Size,0); //File binary sent free(Buffer); printf("sending finished ... \n"); */
}
void timer_start(std::function<void(void)> func, unsigned int interval) {
std::thread([func, interval]() {
while (true)
{
func();
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
}
}).detach(); }
void sending() {
File = fopen("B:\\send.txt","rb"); fseek(File,0,SEEK_END); Size = ftell(File); fseek(File,0,SEEK_SET); printf("Success...\n");
Buffer = (char*) malloc (Size+1) ; fread(Buffer,Size,1,File); fclose(File);
send(clientsock,Buffer,Size,0); //File binary sent free(Buffer); printf("sending finished ... \n");
}
int _tmain(int argc, _TCHAR* argv[]) {
startClient();
timer_start(sending, 10000);
while(true);
//sending();
//Sleep(5000);
system("PAUSE"); return 0;
}
#include "stdafx.h"
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <chrono>
#include <thread>
#include <functional>
SOCKET servsocket, ClientAcc;
WSAData winsock;
sockaddr_in addr,incomingAddress;
int addrlen = sizeof(sockaddr_in);
int addresslen = sizeof(incomingAddress);
char *Filesize = new char[10];
int Size = 0;
char *Buffer = new char[Size];
FILE *File;
void start_p() {
//socket initialization
WSAStartup(MAKEWORD(2,2), &winsock);
//socket check
if(LOBYTE(winsock.wVersion) !=2 || HIBYTE(winsock.wVersion) != 2 ) {
WSACleanup();
}
servsocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
addr.sin_family = AF_INET;
addr.sin_port = htons(6091);
bind(servsocket, (sockaddr*)&addr, sizeof(addr));
listen(servsocket, 5);
ClientAcc = accept(servsocket, (sockaddr*)&incomingAddress, &addresslen);
char *ClientIP = inet_ntoa(incomingAddress.sin_addr);
int ClientPort = ntohs(incomingAddress.sin_port);
printf("Client Connected ... \n");
printf("IP : %s:%d\n", ClientIP, ClientPort);
//receive file size
recv(ClientAcc,Filesize,10,0);
Size = atoi((const char*)Filesize);
printf("File size : %d\n",Size);
}
void timer_start(std::function<void(void)> func, unsigned int interval)
{
std::thread([func, interval]() {
while (true)
{
func();
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
}
}).detach();
}
void receive() {
Buffer = (char*)malloc(Size+1);
int file_dit, total_file = 0 ;
while(total_file < Size) {
ZeroMemory(Buffer,Size);
if((file_dit = recv(ClientAcc,Buffer,Size,0)) < 0 ){
goto END;
} else {
total_file += file_dit;
File = fopen("B:\\fileReceived.txt", "wb");
fwrite((const char*)Buffer,1,file_dit,File);
fclose(File);
Sleep(1000);
}
END:
printf("File received ... \n");
free(Buffer);
closesocket(ClientAcc);
WSACleanup();
getchar();
}
}
int _tmain(int argc, _TCHAR* argv[])
{
start_p();
timer_start(receive, 10000);
//receive();
//Sleep(5000);
system("PAUSE");
return 0;
}
i used this way
to send the file periodically but the result is not what i want.
i hope you can help me . thank you. i really appreciate your help.
The content of the file is not actually written to disk until you close the file. I'm think you are keeping the file open while adding text, you need to close it before the client read again from it.
fclose(file); // Here is when the content is written to disk.
Besides, you aren't closing the file after sending it.
So, every time you perform an operation over the file (handle) you should close it before start another.
And the true error must be that you allways are reading to char cisi[10]
and it has only 10 spaces equally you're only sending 10 characters. send(clientsock,cisi,10,0);
Change the lines:
// ...
char cisi[10];
// ...
send(clientsock,cisi,10,0);
to:
// ...
char *cisi = new char[Size];
// ...
send(clientsock,cisi,Size,0);
About server side code:
recv(ClientAcc,Filesize,10,0);
With the above line of code you always will get 10 chars. But here you don't know how many chars comes from the client.
A basic solution for this is to send that number first (before the file), that way you'll know how chars you have to read for complete the receiving operation.
A complete solution involves the implementation of some protocol. Or the use of a more advanced library (E.g boost.Asio).
Recommendation:
Use fstream to manage files. After all, you're coding in c++. ;D
这篇关于C++ - 定期发送修改过的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!