通过TCP与中间服务器在2个客户端之间传输数据的有效方法

时间:2012-12-21 08:39:24

标签: c tcp pthreads client-server

这是出于教育目的(大学任务)。

我需要在C for Linux中编写客户端 - 服务器程序。 (我已经有了那部分。客户端连接到服务器,它发送和接收文件没有问题......)。

当客户端连接到服务器时,它会向服务器发送客户端上的文件列表。因此,服务器上有一个包含客户端所有文件的列表。

客户端A可以从服务器请求文件" test.txt",服务器知道该文件在客户端B上,并且该文件应该从B转移到A.I'我试图考虑这样做的最佳方式。

  1. 从B恢复到缓冲区,并立即将缓冲区发送()到A?
  2. recv()来自B的整个文件并将其保存在服务器上,然后发送 到A?
  3. 我的程序应支持此行为: 如果A从B询问文件,然后C询问来自B的文件,则C不应该等到转移A< - > B结束。这就是我被卡住的地方。

    非常感谢!!

    编辑:我的服务器正在使用线程:每当新客户端连接时,都会打开一个新线程来提供它。此时,我的客户端不使用线程(可以更改)。

3 个答案:

答案 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次,但只创建了一个线程。 当我尝试发送一个大文件时,我确实得到了一些,但随后出现了“由同行重置连接”...

我希望这里的某个人能够回答我不太好解释的问题。 谢谢。