1

我有一个 tcp 客户端 - 服务器实现在不同的后台工作线程上运行在同一个程序中。在多台计算机上会有这个程序的实例,因此它们可以在彼此之间发送和接收文件。我可以使用网络流在计算机之间按顺序发送文件,但是如何将多个文件同时从计算机 A 发送到 B。

通过一个连接(套接字)发送多个文件很好,但是有多个网络流向客户端发送数据,客户端不知道哪个数据块是哪个文件的一部分?

客户端是否可以两次连接到服务器(在不同的端口上,因为“随机”/未使用的端口被分配给连接)然后每个连接都有自己的流,允许在同时?

感谢您的时间和精力。

4

5 回答 5

5

客户端当然可以多次连接到服务器 - 并且可能应该。

您可以指定相同的服务器端口 - 将在服务器端分配不同的本地端口,但客户端不需要知道这一点。(考虑一个 Web 服务器 -许多客户端都将同时连接到端口 80。)

当然,您也会自动分配到单独的客户端端口 - 基本上这些连接根本不应该相互干扰。

于 2010-11-29T16:41:15.587 回答
3

您需要使用异步客户端和服务器套接字。基本上不使用 Recieve 和 Send,而是使用 BeginRecieve、BeginSend、BeginConnect 和 BeginAccept。这样线程就为你完成了。在工作线程中拥有每个连接并不是一个好主意。这样每个新请求都会同时处理(异步)。您还可以使用已发送文件的前几个字节来存储有关文件的数据。下面的例子。当然,下面的 numbers(1,2,3..) 将是您调用 Bitconverter.GetBytes(String var) 的字符串文件名。希望这可以帮助。maxpfc@gmail.com (Skype)

byte[] completefile = [1,2,3,4,5,6,7,8,9];
byte[] filename;
filename = split(lcomplefile, 3);  

下面是一个可编译的 Asyc 套接字示例。

using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
class AsyncTcpClient Form:
{
private TextBox newText;
private TextBox conStatus;
private ListBox results;
private Socket client;
private byte[] data = new byte[1024];
private int size = 1024;
public AsyncTcpClient()
{
Text = "Asynchronous TCP Client";
Size = new Size(400, 380);
Label label1 = new Label();
label1.Parent = this;
label1.Text = "Enter text string:";
label1.AutoSize = true;
label1.Location = new Point(10, 30);
newText = new TextBox();
newText.Parent = this;
newText.Size = new Size(200, 2 * Font.Height);
newText.Location = new Point(10, 55);
results = new ListBox();
results.Parent = this;
results.Location = new Point(10, 85);
results.Size = new Size(360, 18 * Font.Height);
Label label2 = new Label();
label2.Parent = this;
label2.Text = "Connection Status:";
label2.AutoSize = true;
label2.Location = new Point(10, 330);
conStatus = new TextBox();
conStatus.Parent = this;
conStatus.Text = "Disconnected";
conStatus.Size = new Size(200, 2 * Font.Height);
conStatus.Location = new Point(110, 325);
This document is created with the unregistered version of CHM2PDF Pilot
Button sendit = new Button();
sendit.Parent = this;
sendit.Text = "Send";
sendit.Location = new Point(220,52);
sendit.Size = new Size(5 * Font.Height, 2 * Font.Height);
sendit.Click += new EventHandler(ButtonSendOnClick);
Button connect = new Button();
connect.Parent = this;
connect.Text = "Connect";
connect.Location = new Point(295, 20);
connect.Size = new Size(6 * Font.Height, 2 * Font.Height);
connect.Click += new EventHandler(ButtonConnectOnClick);
Button discon = new Button();
discon.Parent = this;
discon.Text = "Disconnect";
discon.Location = new Point(295,52);
discon.Size = new Size(6 * Font.Height, 2 * Font.Height);
discon.Click += new EventHandler(ButtonDisconOnClick);
}
void ButtonConnectOnClick(object obj, EventArgs ea)
{
conStatus.Text = "Connecting...";
Socket newsock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
newsock.BeginConnect(iep, new AsyncCallback(Connected), newsock);
}
void ButtonSendOnClick(object obj, EventArgs ea)
{
byte[] message = Encoding.ASCII.GetBytes(newText.Text);
newText.Clear();
client.BeginSend(message, 0, message.Length, SocketFlags.None,
new AsyncCallback(SendData), client);
}
void ButtonDisconOnClick(object obj, EventArgs ea)
{
client.Close();
conStatus.Text = "Disconnected";
}
void Connected(IAsyncResult iar)
{
client = (Socket)iar.AsyncState;
try
{
client.EndConnect(iar);
conStatus.Text = "Connected to: " + client.RemoteEndPoint.ToString();
client.BeginReceive(data, 0, size, SocketFlags.None,
new AsyncCallback(ReceiveData), client);
} catch (SocketException)
{
conStatus.Text = "Error connecting";
}
}
void ReceiveData(IAsyncResult iar)
{
Socket remote = (Socket)iar.AsyncState;
int recv = remote.EndReceive(iar);
string stringData = Encoding.ASCII.GetString(data, 0, recv);
results.Items.Add(stringData);
}
void SendData(IAsyncResult iar)
{
Socket remote = (Socket)iar.AsyncState;
int sent = remote.EndSend(iar);
remote.BeginReceive(data, 0, size, SocketFlags.None,
This document is created with the unregistered version of CHM2PDF Pilot
new AsyncCallback(ReceiveData), remote);
}
public static void Main()
{
Application.Run(new AsyncTcpClient());
}
}
于 2012-02-05T15:29:25.390 回答
1

客户端是否可以两次连接到服务器(在不同的端口上,因为“随机”/未使用的端口被分配给连接)然后每个连接都有自己的流,允许在同时?

是的; 这就是网络协议通常的工作方式。你不需要在服务器端选择一个新的端口号:即使你监听一个固定的端口号,到那个端口的连接也是分开的。

例如,www.stackoverflow.com 上的 Web 服务器始终侦听端口 80,但您和我可以从我们的 Web 浏览器连接,并且我们的连接不会混淆。

于 2010-11-29T16:41:20.380 回答
1

你可以这样做,但我看不出有什么好处。除非每个连接都在某处受到限制,否则您基本上会产生两倍的 I/O 操作开销。

这与将文件写入磁盘相同,仅仅因为您将其拆分为两个线程并不意味着它会更快,因为磁盘只能一次写入。您实际上可能会看到响应时间变慢。

于 2010-11-29T16:42:22.417 回答
0

您要么必须在单个套接字上叠加协议以识别哪些数据是哪个文件的一部分,要么使用多个套接字以便您知道每个文件的开始和结束位置。

即使有多个套接字,如果您想在没有套接字打开/关闭内务管理的情况下为新文件重用相同的套接字,则必须具有开始/结束标记。

为什么不能使用 FTP?

于 2010-11-29T16:40:57.533 回答