Metalstorm
Metalstorm

Reputation: 3232

How do I send multiple files over tcp at the same time in c sharp?

I have a tcp client - server implementation running in the same program, on different background worker threads. There will be instances of this program on multiple computers so they can send and receive files between each other. I can send files sequentially between computers using network stream, but how would I send multiple files at the same time from computer A to B.

Sending multiple files over one connection ( socket ) is fine, but having multiple network streams sending data to a client, the client doesn't know which chunk of data is apart of which file ?

Would it be possible for the client to connect twice to the server (on a difference port, as a 'random'/ unused port is assigned to the connection) and then each connection have its own stream, allowing 2 files to be sent at the same time?

Thanks for your time and effort.

Upvotes: 1

Views: 4705

Answers (5)

user416134
user416134

Reputation: 31

You need to use Asyncronous Client and server sockets. Basically instead of using Recieve and Send, use BeginRecieve, BeginSend, BeginConnect and BeginAccept. That way the threading is done for you. Having each connection in a worker thread is not a good idea. This way each new request is handled at the same time(asycronously). You can also use the first few bytes of your sent file to store data about the file. Example below. Of course the numbers(1,2,3..) below would be a string filename that you called Bitconverter.GetBytes(String var) on. hope this helps. [email protected] (skype)

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

Below is a compilable example of 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());
}
}

Upvotes: 3

casperOne
casperOne

Reputation: 74530

You could do that, but I don't see the benefit. Unless the each connection is throttled somewhere down the line, you are essentially incurring twice the overhead of your I/O operations.

It's the same as writing a file to a disk, just because you split it to two threads doesn't mean it will be faster, because the disk can only be written to at one time. You might actually see a slower response time.

Upvotes: 1

Tim Robinson
Tim Robinson

Reputation: 54734

Would it be possible for the client to connect twice to the server (on a difference port, as a 'random'/ unused port is assigned to the connection) and then each connection have its own stream, allowing 2 files to be sent at the same time?

Yes; this is how network protocols typically work. You don't need to choose a new port number on the server side: even if you listen on a fixed port number, connections to that port are kept separate.

For instance, the web server at www.stackoverflow.com always listens on port 80, yet you and I can connect from our web browsers, and our connections don't get mixed up.

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500495

The client could certainly connect to the server multiple times - and probably should.

You can specify the same server port though - a different local port will be assigned at the server side, but the client doesn't need to know about that. (Think about a web server - lots of clients will all connect to port 80 at the same time.)

You'll automatically be assigned separate client side ports as well, of course - basically the connections shouldn't interfere with each other at all.

Upvotes: 5

Steve Townsend
Steve Townsend

Reputation: 54148

You either have to superimpose a protocol on a single socket to identify what data is part of what file, or use multiple sockets so that you know where each file begins and ends.

Even with multiple sockets, you have to have start/end markers if you want to reuse the same socket for a new file without socket open/close housekeeping.

Why can't you use FTP?

Upvotes: 0

Related Questions