这是出于教育目的(大学任务)。
我需要在C for Linux中编写客户端 - 服务器程序。 (我已经有了那部分。客户端连接到服务器,它发送和接收文件没有问题......)。
当客户端连接到服务器时,它会向服务器发送客户端上的文件列表。因此,服务器上有一个包含客户端所有文件的列表。
客户端A可以从服务器请求文件" test.txt",服务器知道该文件在客户端B上,并且该文件应该从B转移到A.I'我试图考虑这样做的最佳方式。
我的程序应支持此行为: 如果A从B询问文件,然后C询问来自B的文件,则C不应该等到转移A< - > B结束。这就是我被卡住的地方。
非常感谢!!
编辑:我的服务器正在使用线程:每当新客户端连接时,都会打开一个新线程来提供它。此时,我的客户端不使用线程(可以更改)。
答案 0 :(得分:1)
如果您想使用套接字一次进行多次传输,您有两种选择:
阻止套接字和线程
这是您编写服务器的方式。线程的问题是它们可能导致很难调试的错误。将其与网络错误相结合,这些错误本身可能很难调试,并且您手上有潜在的噩梦调试会话。
非阻塞套接字和select()
这种方式不需要线程,而是使用select()来查看哪些套接字有等待读取的数据。将它与一些循环相结合,您可以同时传输多个文件。将套接字设置为非阻塞是很容易的,使用正确可能会稍微复杂一些,但加重线程+网络错误的可能性这是我个人更喜欢编写网络代码的方式。
关于你的实际问题;我会建议这样的事情:
Client A connects to server S. You need to bind the local side for the next step.
A also opens another socket for data transfer on the next port upwards.
S sends file list to A. How you build up the file list I leave to you.
A requests file F from S.
S checks which client has F.
S sends "send F to A on port X" to B. You can check which remote port is used, and then you know which port to send the file on.
B recieves and executes the command.
答案 1 :(得分:0)
你必须为每个客户端连接2个套接字,所以你将有4个这样的套接字:
1 A <-> C
2 B <-> C
3 A <-> C <-> B 4
因此,您必须使用套接字1和2在客户端A和服务器C(socket1)之间以及客户端B和服务器C(套接字2)之间传输文件。
然后你必须使用套接字3和4在服务器C中开发一个桥,以便将数据从A传输到B.
我想,多线程解决方案应该可行!
答案 2 :(得分:0)
到目前为止我得到了什么: 服务器仅使用select()运行。 客户端在listen()模式下有一个套接字 - 称之为dataSocket(在它的常规套接字之上)。 如果客户端A想要一个文件,它会告诉服务器文件名。服务器找到具有该文件的用户,并为dataSocket创建一个connet()。 (我设法实现了这一点。)
传输小文件没有问题。大文件失败。
我认为这是因为我的客户出了点问题。 我已经使用select()函数实现了客户端,如果发现某个人正在执行connect(),它会打开一个新线程并提供请求。但有些事情是错的...... 代码是这样的:
FD_SET(globalSocket,&origin);
FD_SET(dataSocket,&origin);
FD_SET(STDIN,&origin); //#define STDIN 0
while(1)
{
readfds=origin;
select(fdmax+1,&readfds,NULL,NULL,NULL);
for(i=0;...)
{
if(FD_ISSET(i,&readfds)
{
if(i==STDIN)
// get user input
if(i==dataSocket)
{
printf("someone wants a file from me");
pthread_create(...);
}
}
}
}
我看到的一个问题是,当我第一次请求文件时,它打印“有人想要我的文件”行2或3次,但只创建了一个线程。 当我尝试发送一个大文件时,我确实得到了一些,但随后出现了“由同行重置连接”...
我希望这里的某个人能够回答我不太好解释的问题。 谢谢。