我正在尝试编写一个程序,该程序使用 C++ 通过 Internet(或 LAN)将基本文本文件从一台计算机发送到另一台计算机。我正在研究 Winsock,但我读到的所有内容都让它看起来只是用于服务器和客户端之间的通信。我不确定这是否是我想要做的,或者我是否正在寻找一个不同的问题。
编辑:谢谢你们的精彩回答。我有点为不得不从很多中选择一个最好的而感到难过。
我正在尝试编写一个程序,该程序使用 C++ 通过 Internet(或 LAN)将基本文本文件从一台计算机发送到另一台计算机。我正在研究 Winsock,但我读到的所有内容都让它看起来只是用于服务器和客户端之间的通信。我不确定这是否是我想要做的,或者我是否正在寻找一个不同的问题。
编辑:谢谢你们的精彩回答。我有点为不得不从很多中选择一个最好的而感到难过。
这是如何在 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/%d\n",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);
}
编译:
将服务器运行为./server
. 然后复制rngoidiot.txt
,运行客户端,./client rngoidiot.txt
文件将使用 TCP/IP 复制。简单的组合;-)
A client-server architecture should be fine for sending files. The "server" is simply the program that starts first, and waits for the other (the client) to connect to it. Past there, there's not a lot of difference between the two. In a lot of cases, it's easiest to write the code so it automatically attempts to contact a server, and if it can't find one, it sets itself up as the server.
Also note that making things work across the internet with (particularly) NAT routers involved can make the code a little trickier. It's not all that tough if you pre-configure the firewall to allow the connection(s), but otherwise you typically end up using UPnP to establish the connection through the firewall. That can easily double the work compared to doing the job locally without NAT involved.
In short: Yes, sockets are the way to go.
"Server" and "client" in the sockets sense are generic terms - your system is running a variety of both at any given time. For example, your web browser operates as an HTTP client (where HTTP is a text-bounded mostly-synchronous protocol running over TCP/IP); Windows file sharing and remote desktop are "servers" that other systems connect into.
The distinction between server and client in the sockets sense (really in the TCP/IP sense) is that a "server" socket listens for incoming connections from remote systems (refer to MSDN or man pages on bind(), listen(), accept()) whereas a "client" socket creates outgoing connections to remote systems (connect()).
Beware that sockets programming can be a bit tricky. What you describe is a good learning exercise, but if you're trying to get something done quickly, you might look at existing tools such as netcat.
似乎仅用于服务器和客户端之间的通信
所以呢?将一台计算机(即将接收文件)作为服务器。在该计算机上创建一个套接字并使其侦听端口上的连接。一旦连接到达,根据一些定义的结构获取数据(见下文)
发送方计算机(客户端)将连接到另一台计算机,它知道 IP 地址和端口号。(客户端必须知道这两者才能进行连接)。建立连接后,它将以字节序列的形式将数据发送到服务器。
结构:
在这里进行通信的两台计算机必须具有明确定义的结构,并且两者都知道并接受。最简单的结构将是:
|Length-Of-Data | Data ...... |
<-- 4 bytes---> <-- n bytes-->
n
从前 4 个字节开始读取。这里的4
字节 ( n
) 代表数据的长度,可能会有所不同,这是您的定义。
对于文件名、文件类型等,您可以拥有更多“字段”(取决于功能)。
如果你想通过互联网发送文件,你必须使用套接字,或者更好的其他用套接字实现的高级库。
在 TCP 套接字术语中,客户端和服务器之间没有太大区别:通信是两种方式。唯一的区别在于谁在侦听传入连接(绑定、侦听、接受),以及谁在启动连接(打开)。
你提到了 Winsock,这意味着你在 Windows 上工作。查看 Windows API,您可能会找到一些处理文件传输的高级库(如 FTP 或 HTTP 库)。
也许不符合您的要求,但您也可以将共享文件夹用于 LAN 和 Dropbox 同步的文件夹用于 Internet ......然后只需使用标准 IO。
一般来说,任何文件传输都需要某种服务器/客户端连接。一台计算机需要启动连接,另一台计算机需要在另一端侦听连接,然后执行第一台计算机指示的操作。
虽然您当然可以使用套接字推出自己的客户端和服务器软件,但取决于您想要在哪些类型的计算机之间传输文件,利用一些现有的客户端/服务器协议可能是最有意义的。一些更流行的可能性包括 ssh、http 或 ftp。我认为所有这些协议都应该存在 C/C++ 库。
如果没有更多信息,我会倾向于使用 ssh。安装一个 ssh 服务器应该不会太难,所以你只需要编写客户端软件,我认为为此存在一些非常好的开源库。
编辑:libssh看起来不错!