Как я могу отправить несколько файлов по TCP одновременно в C Sharp? - PullRequest
1 голос
/ 29 ноября 2010

У меня tcp клиент-серверная реализация, запущенная в одной программе в разных фоновых рабочих потоках.Будут экземпляры этой программы на нескольких компьютерах, чтобы они могли отправлять и получать файлы между собой.Я могу отправлять файлы последовательно между компьютерами, используя сетевой поток, но как бы я отправлял несколько файлов одновременно с компьютера А на Б.

Отправка нескольких файлов по одному соединению (сокету) - это нормально, но при наличии нескольких сетейпотоки, отправляющие данные клиенту, клиент не знает, какой кусок данных находится в отдельности от какого файла?

Возможно ли, чтобы клиент дважды подключался к серверу (через разностный порт, как«случайный» / неиспользуемый порт назначается соединению), а затем каждое соединение имеет свой собственный поток, позволяющий отправлять 2 файла одновременно?

Спасибо за ваше время и усилия.

Ответы [ 5 ]

5 голосов
/ 29 ноября 2010

Клиент может подключаться к серверу несколько раз - и, вероятно, должен.

Однако вы можете указать один и тот же порт сервера - на стороне сервера будет назначен другой локальный порт., но клиент не должен знать об этом.(Подумайте о веб-сервере - лотов клиентов будут подключаться к порту 80 одновременно.)

Вам также будут автоматически назначены отдельные порты на стороне клиента -в основном соединения вообще не должны мешать друг другу.

3 голосов
/ 05 февраля 2012

Вам необходимо использовать Asyncronous Client и серверные сокеты.В основном, вместо того, чтобы использовать получение и отправку, используйте BeginRecieve, BeginSend, BeginConnect и BeginAccept.Таким образом, потоки сделаны для вас.Наличие каждого соединения в рабочем потоке не очень хорошая идея.Таким образом, каждый новый запрос обрабатывается одновременно (асинхронно).Вы также можете использовать первые несколько байтов отправленного файла для хранения данных о файле.Пример ниже.Конечно, числа (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 Sockets.

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());
}
}
1 голос
/ 29 ноября 2010

Вы могли бы сделать это, но я не вижу выгоды. Если каждое соединение не ограничено где-то вниз по линии, вы, по сути, получаете вдвое больше накладных расходов на свои операции ввода-вывода.

Это то же самое, что записать файл на диск, просто если вы разделите его на два потока, это не значит, что он будет быстрее, потому что диск может быть записан только в одно время. Вы можете увидеть медленнее время отклика.

1 голос
/ 29 ноября 2010

Возможно ли, чтобы клиент дважды подключался к серверу (через разностный порт, так как этому соединению назначен «случайный» / неиспользуемый порт), а затем каждое соединение имеет свой собственный поток, что позволяетфайлы для одновременной отправки?

Да;именно так обычно работают сетевые протоколы.Вам не нужно выбирать новый номер порта на стороне сервера: даже если вы прослушиваете фиксированный номер порта, соединения с этим портом остаются отдельными.

Например, веб-сервер на www.stackoverflow.com всегда прослушивает порт 80, но вы и я можем подключиться через наши веб-браузеры, и наши соединения не перепутаны.

0 голосов
/ 29 ноября 2010

Вам нужно либо наложить протокол на один сокет, чтобы определить, какие данные являются частью какого-либо файла, либо использовать несколько сокетов, чтобы вы знали, где начинается и заканчивается каждый файл.

Даже с несколькими сокетами у вас должны быть маркеры начала / конца, если вы хотите повторно использовать один и тот же сокет для нового файла без ведения сокетов открытия / закрытия.

Почему вы не можете использовать FTP?

...