在具有C++的计算机之间发送文件
Sending files between computers with C++
我正在尝试编写一个程序,该程序通过互联网(或局域网)使用C++将基本文本文件从一台计算机发送到另一台计算机。我正在研究Winsock,但我读到的所有内容似乎仅用于服务器和客户端之间的通信。我不确定这是否是我想做的,或者我是否正在研究不同的问题。
编辑:感谢伟大的答案伙计们。我有点为不得不从中选择一个最好的而感到难过。
客户端-服务器体系结构应该适合发送文件。"服务器"只是首先启动的程序,并等待另一个(客户端)连接到它。过去,两者之间没有太大区别。在很多情况下,编写代码是最容易的,这样它就会自动尝试联系服务器,如果找不到服务器,它会将自己设置为服务器。
另请注意,使用(特别是)涉及的NAT路由器在互联网上工作会使代码更加棘手。如果预先配置防火墙以允许连接,则并不难,但否则通常最终会使用 UPnP 通过防火墙建立连接。与在没有NAT的情况下在本地完成工作相比,这很容易使工作量翻倍。
下面是如何在 Linux 中使用 C/C++ 复制/传输文件的示例。server
侦听端口 8080。client
传输文件名。server
接收文件名,打开文件并将其内容发送到客户端。为了说明目的,我故意使用奇数或小缓冲区大小。
server.c
文件:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
int main (int argc,char *argv[])
{
struct sockaddr_in p;
struct sockaddr_in q;
int z,s,t,x,n,b = sizeof(q);
char buf[23];
int fd;
s = socket(AF_INET,SOCK_STREAM,0);
bzero (&p,sizeof(p));
p.sin_family = AF_INET;
p.sin_addr.s_addr = INADDR_ANY;
p.sin_port = htons(8080);
bind (s,(struct sockaddr*)&p,sizeof(p));
listen(s,13);
while (1) {
t = accept (s,(struct sockaddr*)&q, &b);
n = read(t,buf,23);
buf[n] = 0;
printf("%s sent: ",buf);
fd = open (buf,O_RDONLY);
z = lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
x = 0;
do {
n = read (fd,buf,23);
write (t,buf,n);
x += n;
} while (x < z);
printf("%d/%dn",x,z);
close(fd);
close(t);
}
}
client.c
文件:
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
void main (int argc, char *argv[])
{
int ret;
char buf[5];
int s,n,fd;
struct sockaddr_in p;
struct hostent *h;
char *str = argv[1];
fd = open (str,O_CREAT | O_WRONLY,S_IRUSR|S_IWUSR);
h = gethostbyname("127.0.0.1");
bzero(&p,sizeof(p));
p.sin_family = AF_INET;
p.sin_addr.s_addr = htonl(INADDR_ANY);
p.sin_addr.s_addr = ((struct in_addr*)(h->h_addr))->s_addr;
p.sin_port = htons(8080);
s = socket (AF_INET,SOCK_STREAM,0);
connect (s,(void*)&p,sizeof(p));
n = write (s,str,strlen(str));
int idx = 0;
do {
n = read (s,buf,5);
idx += n;
printf(".");
fflush(stdout);
write (fd,buf,n);
} while (n > 0);
close (fd);
close (s);
}
要编译:
- 打开终端
- gcc -o 服务器服务器.c
- gcc -o client client.c
按./server
运行服务器。然后要复制rngoidiot.txt
,请按./client rngoidiot.txt
运行客户端,文件将使用TCP/IP复制。简单的组合 ;-)
简而言之:是的,套接字是要走的路。
套接字意义上的"服务器"和"客户端"是通用术语 - 您的系统在任何给定时间都运行着各种两者。例如,您的 Web 浏览器作为 HTTP 客户端运行(其中 HTTP 是通过 TCP/IP 运行的文本边界大部分同步协议);Windows 文件共享和远程桌面是其他系统连接到的"服务器"。
在套接字意义上(实际上是在TCP/IP意义上)服务器和客户端之间的区别在于,"服务器"套接字侦听来自远程系统的传入连接(请参阅MSDN或bind(),listen(),accept()上的手册页),而"客户端"套接字创建到远程系统的传出连接(connect())。
请注意,套接字编程可能有点棘手。你描述的是一个很好的学习练习,但如果你想快速完成一些事情,你可以看看现有的工具,如netcat。
似乎仅用于服务器和客户端之间的通信
那又怎样?使一台计算机(即将接收文件)成为服务器。在该计算机上创建一个套接字,并使其侦听端口上的连接。连接到达后,根据某些定义的结构获取数据(见下文)
发送方计算机(客户端)将连接到另一台计算机,并且它知道 IP 地址和端口号。(客户端必须知道这两者才能进行连接)。建立连接后,它会将数据作为字节序列发送到服务器。
结构:
在此处进行通信的两台计算机必须具有双方都知道并接受的明确定义的结构。最简单的结构是:
|Length-Of-Data | Data ...... |
<-- 4 bytes---> <-- n bytes-->
从前 4 个字节读取n
。这里的4
字节(n
)代表数据的长度,可能不同,这是您的定义。
您可以为文件名、文件类型等提供更多"字段"(取决于功能)。
通过互联网发送文件,你必须使用套接字,或者更好的是使用套接字实现的其他高级库。
在TCP套接字术语中,客户端和服务器之间没有太大区别:通信是双向的。唯一的区别在于谁在侦听传入的连接(绑定、侦听、接受)和谁在启动连接(打开)。
你提到了Winsock,这意味着你正在Windows上工作。看看Windows API,也许你可以找到一些处理文件传输的高级库(如FTP或HTTP库)。
也许不符合您的要求,但您也可以使用共享文件夹作为局域网和由 Dropbox 同步的文件夹用于互联网......然后只需使用标准 IO。
一般来说,任何文件传输都需要某种服务器/客户端连接。 一台计算机需要启动连接,另一台计算机需要在另一端侦听连接,然后执行第一台计算机指示的操作。
虽然您当然可以使用套接字推出自己的客户端和服务器软件,但根据您要在哪种计算机之间传输文件,利用一些现有的客户端/服务器协议可能是最有意义的。 一些更流行的可能性包括ssh,http或ftp。 我认为所有这些协议都应该存在 C/C++ 库。
如果没有更多信息,我会倾向于使用 ssh。 安装 ssh 服务器不应该太难,所以你只需要编写客户端软件,我认为有一些非常好的开源库。
编辑:libssh看起来相当不错!
- 如何在cpp文件之间切换窗口?在Qt中
- 如何使用管道在父级和子级之间来回传递文件
- 共享库 (.so) 没有扩展名的 Linux 可执行文件之间的区别?
- 在.cpp文件之间传递结构声明,而不使用全局头文件
- 内联函数的函数本地静态对象是否在共享对象文件之间共享?
- 在.cpp文件之间传递全局字符串变量?
- 如何在 的开头<x>和结尾<y>之间更改带有文件输出的字符串的值
- 在两个.cpp文件之间定义全局类/结构指针
- 文件删除(使用取消链接)与释放所有磁盘空间之间的延迟
- CSV文件之间的差异,使用getline()产生不同的结果
- 检测到 Conan 配置文件设置与 CMake 之间的编译器版本不匹配
- 如何从txt文件c++中提取括号之间的数字
- 包括两个文件 C++ 之间的冲突
- 在没有外部文件的情况下在应用会话之间保存变量
- 如何读取特定单词之间的文本文件?
- OpenCV 文件存储 - 错误:元素之间的解析错误 (icvYMLParseValue) 缺失
- 为什么 .cpp 文件和 .h 文件之间有区别?
- 在结构函数之间传递文件路径 C++ 编辑:修复LNK2019错误
- 在头文件和 .cc 文件之间建立关系
- CPP项目中.fdf和.h文件之间的差异