C# async socket file transfer - c#

Well I'm trying to write a C# server application which will receive files from several clients written in C++ and the main problem is I'm pretty new to C# .Net.
Got managed to write one code for sync socket C# server but couldn't figure out how to receve data for an async socket byte wise and write those to a single file inside OnDataReceive callback.
public void OnDataReceived(IAsyncResult asyn)
{
try
{
SocketPacket socketData = (SocketPacket)asyn.AsyncState;
////Original code inside this function
//int iRx = socketData.m_currentSocket.EndReceive(asyn);
//char[] chars = new char[iRx + 1];
//System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
//int charLen = d.GetChars(socketData.dataBuffer, 0, iRx, chars, 0);
//System.String szData = new System.String(chars);
//richTextBoxReceivedMsg.AppendText(szData);
////My old code from Sync socket file transfer
//Receive data from client socket till it continues
byte[] bufferData = new byte[1024];
int recvBytesLen = 0;
BinaryWriter bWrite = new BinaryWriter(File.Open(m_strCurrFolder + "File", FileMode.Append));
do
{
recvBytesLen = clientSock.Receive(bufferData, bufferData.Length, 0);
bWrite.Write(bufferData, 0, recvBytesLen);
} while (recvBytesLen > 0);
//Closing file and socket once done
bWrite.Close();
// Continue the waiting for data on the Socket
WaitForData(socketData.m_currentSocket);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}

Found this link to be helpful and does my job.
https://code.msdn.microsoft.com/windowsapps/Fixed-size-large-file-dfc3f45d
private static void ReceiveCallback(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
Socket clientSocket = state.WorkSocket;
BinaryWriter writer;
int bytesRead = clientSocket.EndReceive(ar);
if (bytesRead > 0)
{
//If the file doesn't exist, create a file with the filename got from server. If the file exists, append to the file.
if (!File.Exists(fileSavePath))
{
writer = new BinaryWriter(File.Open(fileSavePath, FileMode.Create));
}
else
{
writer = new BinaryWriter(File.Open(fileSavePath, FileMode.Append));
}
writer.Write(state.Buffer, 0, bytesRead);
writer.Flush();
writer.Close();
// Notify the progressBar to change the position.
Client.BeginInvoke(new ProgressChangeHandler(Client.ProgressChanged));
// Recursively receive the rest file.
try
{
clientSocket.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
catch
{
if (!clientSocket.Connected)
{
MessageBox.Show(Properties.Resources.DisconnectMsg);
}
}
}
else
{
// Signal if all the file received.
receiveDone.Set();
}
}

Related

How receive a complete screenshot in Async socket?

I have a Java android code that sends data (image or text) to a C# application, to receive these data I'm using Async socket. But exists a problem that is relative to BeginReceive() function is not receiving the complete data when is sent an image.. Then how I can make a kind of "loop" to receive full data and after show the image on Picturebox (for example)?
Form
private Listener listener;
private Thread startListen;
private Bitmap _buffer;
public frmMain()
{
InitializeComponent();
}
private void serverReceivedImage(Client client, byte[] image)
{
try
{
byte[] newImage = new byte[image.Length - 6];
Array.Copy(image, 6, newImage, 0, newImage.Length);
using (var stream = new MemoryStream(newImage))
{
using (var msInner = new MemoryStream())
{
stream.Seek(2, SeekOrigin.Begin);
using (DeflateStream z = new DeflateStream(stream, CompressionMode.Decompress))
{
z.CopyTo(msInner);
}
msInner.Seek(0, SeekOrigin.Begin);
var bitmap = new Bitmap(msInner);
Invoke(new frmMain.ImageCompleteDelegate(ImageComplete), new object[] { bitmap });
}
}
}
catch (Exception)
{
System.Diagnostics.Process.GetCurrentProcess().Kill();
}
}
private delegate void ImageCompleteDelegate(Bitmap bitmap);
private void ImageComplete(Bitmap bitmap)
{
if (_buffer != null)
_buffer.Dispose();
_buffer = new Bitmap(bitmap);
pictureBox1.Size = _buffer.Size;
pictureBox1.Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (_buffer == null) return;
e.Graphics.DrawImage(_buffer, 0, 0);
}
private void startToolStripMenuItem_Click(object sender, EventArgs e)
{
startListen = new Thread(listen);
startListen.Start();
}
private void listen()
{
listener = new Listener();
listener.BeginListen(101);
listener.receivedImage += new Listener.ReceivedImageEventHandler(serverReceivedImage);
startToolStripMenuItem.Enabled = false;
}
Listener
class Listener
{
private Socket s;
public List<Client> clients;
public delegate void ReceivedImageEventHandler(Client client, byte[] image);
public event ReceivedImageEventHandler receivedImage;
private bool listening = false;
public Listener()
{
clients = new List<Client>();
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
public bool Running
{
get { return listening; }
}
public void BeginListen(int port)
{
s.Bind(new IPEndPoint(IPAddress.Any, port));
s.Listen(100);
s.BeginAccept(new AsyncCallback(AcceptCallback), s);
listening = true;
}
public void StopListen()
{
if (listening == true)
{
s.Close();
listening = false;
}
}
void AcceptCallback(IAsyncResult ar)
{
Socket handler = (Socket)ar.AsyncState;
Socket sock = handler.EndAccept(ar);
Client client = new Client(sock);
clients.Add(client);
sock.BeginReceive(client.buffer, 0, client.buffer.Length, SocketFlags.None, new AsyncCallback(ReadCallback), client);
client.Send("REQUEST_PRINT" + Environment.NewLine);
handler.BeginAccept(new AsyncCallback(AcceptCallback), handler);
}
void ReadCallback(IAsyncResult ar)
{
Client client = (Client)ar.AsyncState;
try
{
int rec = client.sock.EndReceive(ar);
if (rec != 0)
{
string data = Encoding.UTF8.GetString(client.buffer, 0, rec);
if (data.Contains("SCREEN"))
{
byte[] bytes = Encoding.UTF8.GetBytes(data);
receivedImage(client, bytes);
}
else // not is a image, is a text
{
// prepare text to show in TextBox
}
}
else
{
Disconnected(client);
return;
}
client.sock.BeginReceive(client.buffer, 0, client.buffer.Length, SocketFlags.None, new AsyncCallback(ReadCallback), client);
}
catch
{
Disconnected(client);
client.sock.Close();
clients.Remove(client);
}
}
}
Client
class Client
{
public Socket sock;
public byte[] buffer = new byte[8192];
public Client(Socket sock)
{
this.sock = sock;
}
public void Send(string data)
{
byte[] buffer = Encoding.ASCII.GetBytes(data);
sock.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback((ar) =>
{
sock.EndSend(ar);
}), buffer);
}
}
Android code
private byte[] compress(byte[] data) {
Deflater deflater = new Deflater();
deflater.setInput(data);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
deflater.finish();
byte[] buffer = new byte[1024];
while (!deflater.finished()) {
int count = deflater.deflate(buffer);
outputStream.write(buffer, 0, count);
}
outputStream.close();
byte[] output = outputStream.toByteArray();
return output;
}
public static DataOutputStream dos;
public static byte[] array;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
array = compress(bos.toByteArray());
//...
dos = new DataOutputStream(SocketBackgroundService.clientSocket.getOutputStream());
byte[] header = ("SCREEN").getBytes(StandardCharsets.UTF_8);
byte[] dataToSend = new byte[header.length + array.length];
System.arraycopy(header, 0, dataToSend, 0, header.length);
System.arraycopy(array, 0, dataToSend, header.length, array.length);
dos.writeInt(dataToSend.length);
dos.write(dataToSend, 0, dataToSend.length);
dos.flush();
EDITION
i'm always getting the error Invalid Parameter in this line
var bitmap = new Bitmap(msInner);
and using compression also happens the same here
z.CopyTo(msInner);
IvalidDataException
on ServerReceivedImage() method respectively.
using this
File.WriteAllBytes(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "image.png"), newImage);
i noted that is receiving only 15KB (size of file without use compression).
I was writing a comment but it does not give me enough space to express my frustration with your code.
My main points are
You try to recompress and perfectly compressed image. PNG is portable network graphics. It was designed for network transfers. If it is acceptable you should use something like jpeg.
You just decode received buffer using UTF8.GetString and search for a text, then re-encode that string and try to decompress and read an image from it, by starting from index 6 which is pretty meaningless considering you added a two byte size field to the start of stream and you really do not know position of "SCREEN".
You do not check if you have received ALL of the stream data.
All of the code looks like you have scoured the SO questions and answers and created a copy pasta.
Now my recommendations.
When transferring data from network, do not try to invent wheels. Try something like gRPC which has both android java and c# packages.
If you will use raw data, please, please know your bytes.
I assume you will extend your code by adding new command pairs. Since you have no magic markers of some kind of signal system, it will be very hard for you to distinguish data from header. For a simple implementation add some kind of magic data to your header and search for that data, then read header and then read data. You may need to read from socket again and again until you receive all of the data.
424A72 0600 53435245454E 008E0005 ..... 724A42
B J r 6 S C R E E N 36352 ..... rJB
this sample data shows that we have a valid stream by looking at "BJr". Then read a 2 byte unsigned integer to read command size which is 6 for SCREEN. Read command and then read four bytes unsigned length for command data. For our sample it is 36352. Just to be safe I've added an end of command marker "rJB".
For a bonus point try reducing memory allocations / copies, you can look at System.Span<T>

Sending and receiving files keeps hanging

my program should be able to send and receive files but for some reason whenever i click on the send (button1) and receive (button2) buttons, it keeps hanging. Not sure if its something wrong my my codes? Also, I feel like my codes are pretty long as compared to other examples i found online but I'm not sure how to rectify.
Client codes
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9000);
private void Form1_Load(object sender, EventArgs e)
{
try
{
socket.Connect(remoteEP);
textBox2.Text = "Connected to Server";
}
catch (Exception ex)
{
textBox2.Text = "Unable to connect to Server";
textBox2.Text = ex.Message;
}
}
public const string SEND = "[SEND]";
public const string RECEIVE = "[RECEIVE]";
public const string QUIT = "[QUIT]";
private void button1_Click(object sender, EventArgs e)
{
textBox1.Clear();
textBox2.Clear();
NetworkStream stream = new NetworkStream(socket);
StreamReader reader = new StreamReader(stream);
StreamWriter writer = new StreamWriter(stream);
try
{
writer.WriteLine(RECEIVE);
writer.Flush();
writer.WriteLine(textBox1.Text);
writer.Flush();
Bitmap bmp = new Bitmap(#"C:\Users\Y400\Desktop\Lectures\Year 3\WAD\Week 11" + textBox1.Text);
MemoryStream ms = new MemoryStream();
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] bmpBytes = ms.GetBuffer();
bmp.Dispose();
ms.Close();
int sent;
sent = sendData(socket, bmpBytes);
textBox1.Text = "Transferring file complete\r\n";
textBox1.Text += bmpBytes.Length + " bytes sent to Server.";
}
catch (Exception ex)
{
textBox2.Text = ex.Message;
}
}
public static int sendData (Socket s, byte[] data)
{
int total = 0;
int size = data.Length;
int left = size;
int sent;
byte[] datasize = new byte[4];
datasize = BitConverter.GetBytes(size);
sent = s.Send(datasize);
while(total<size)
{
sent = s.Send(data, total, left, SocketFlags.None);
total += sent;
left -= sent;
}
return total;
}
private void button2_Click(object sender, EventArgs e)
{
textBox2.Clear();
textBox1.Clear();
byte[] data = new byte[1024];
string fileN = textBox2.Text.Trim();
NetworkStream ns = new NetworkStream(socket);
StreamReader reader = new StreamReader(ns);
StreamWriter writer = new StreamWriter(ns);
writer.WriteLine(SEND);
writer.Flush();
writer.WriteLine(fileN);
writer.Flush();
try
{
while (true)
{
data = receiveData(socket);
MemoryStream ms = new MemoryStream(data);
break;
}
textBox2.Text = ("Receiving file from server ...\r\n" + data.Length + " bytes copied");
}
catch (Exception ex)
{
textBox2.Text = ex.Message;
}
}
public static byte[] receiveData (Socket s)
{
int total = 0;
int recv;
byte[] datasize = new byte[4];
recv = s.Receive(datasize, 0, 4, 0);
int size = BitConverter.ToInt32(datasize, 0);
int dataleft = size;
byte[] data = new byte[size];
while (total < size)
{
recv = s.Receive(data, total, dataleft, 0);
if (recv == 0)
{
break;
}
total += recv;
dataleft -= recv;
}
return data;
}
private void button3_Click(object sender, EventArgs e)
{
textBox1.Clear();
textBox2.Clear();
textBox2.Text = "Connection closed";
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
Server codes
class Program
{
public const string SEND = "[SEND]";
public const string RECV = "[RECV]";
public const string QUIT = "[QUIT]";
static void Main(string[] args)
{
runServer();
}
static void runServer()
{
try
{
byte[] data = new byte[1024];
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint localEP = new IPEndPoint(IPAddress.Any, 9000);
server.Bind(localEP);
server.Listen(10);
Console.WriteLine("Waiting for Client ...");
Socket client = server.Accept();
Console.WriteLine("Client connected");
NetworkStream stream = new NetworkStream(client);
StreamReader reader = new StreamReader(stream);
StreamWriter writer = new StreamWriter(stream);
try
{
while(true)
{
string request = reader.ReadLine();
string filename = reader.ReadLine();
if (request == QUIT)
{
Console.WriteLine("Client disconnected");
break;
}
else if (request == SEND)
{
getFileFromClient(filename, client);
}
else if (request == RECV)
{
receiveFileFromClient(filename, client);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public static void getFileFromClient(string filename, Socket client)
{
try
{
FileStream output = File.OpenWrite(filename);
Console.WriteLine(filename + " created");
int count = 0;
while(true)
{
byte[] data = new byte[1024];
int size = client.Receive(data);
output.Write(data, 0, size);
count += size;
if(size<1024)
{
break;
}
}
output.Close();
Console.WriteLine(count + " bytes read from client");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public static void receiveFileFromClient(string filename, Socket client)
{
int count = 0;
FileStream input = File.OpenRead(filename);
Console.WriteLine("Reading " + filename);
while(true)
{
byte[] data = new byte[1024];
int bytesRead = input.Read(data, 0, 1024);
client.Send(data, bytesRead, SocketFlags.None);
count += bytesRead;
if(bytesRead < 1024)
{
break;
}
}
Console.WriteLine("Transferring file completed\r\n" + count + " bytes sent to Client");
input.Close();
}
}
Generally speaking
...try to approach the problem differently.
You can't just copy paste stuff from the Internet and hope for the best. You need to understand what you're doing thoroughly.
Regarding your exact problem
Take a look at the button2_Click method.
It contains a while loop which apparently never finishes.
while (true)
{
data = receiveData(socket);
MemoryStream ms = new MemoryStream(data);
break;
}
It does finish because of the break command. But this is all very hard to read.
When you copy paste code around and then apply quick fixes you end up with a pile of code which is very hard to debug.
It took me about 10 minutes to notice the fact that the client defines it's "message verbs" like so:
public const string SEND = "[SEND]";
public const string RECEIVE = "[RECEIVE]";
public const string QUIT = "[QUIT]";
while the server defines them like so:
public const string SEND = "[SEND]";
public const string RECV = "[RECV]";
public const string QUIT = "[QUIT]";
This is maybe not the only problem, but it is sufficient to create a deadlock,
because the server never executes the positive branch of this if statement:
else if (request == RECV)
{
receiveFileFromClient(filename, client);
}
so the client believes it is about to receive something, which proves to be false.
Also make sure you send the "SEND" and "RECEIVE" message verbs when you should and not mix them up.
Good luck!
PS: I would suggest you take a look at more simpler to use techniques for sending and receiving data, such as:
WCF
ASP.NET Web Services
Web API
Ignoring any logic errors that may occur in your programs, the way you are handling things in your client whenever it is doing an action it is doing it on the GUI thread. This will make your application seem like it is locking but instead it is executing your logic on the GUI thread.
The same problem is occurring on the server. It accepts a connection, and then goes on to receive the file. It will not be able to receive any other connection until it finished receiving the file.
The server is not without problems either because it is never checking if it receives 0 bytes from the socket. Which means that the client closed its end of the connection. You are simply assuming that if you receive less than 1024 you are receiving your last part of the file. This is simply not true for TCP. You only know you received the last part if you receive 0 bytes. TCP is a byte streaming protocol you cannot assume you will be receiving blocks of 1024 bytes. It is likely that this will be in fact the case, but you should not code it like that. Check for reception of 0 bytes. On the client you did check for 0 bytes, I am puzzled why you did not do the same on the server. The problematic part is this :
byte[] data = new byte[1024];
int size = client.Receive(data);
output.Write(data, 0, size);
count += size;
if(size<1024) //you can only break if the size is 0
{
break;
}
There are probably more bugs. As the other answer also indicated some other issues.

Async socket confusion

My socket client does not appear to be handling situations where the buffer is full and there is more data to be received.
Here is my on receive method, simple version:
private void Recieve()
{
this._clientSocket.BeginReceive(this._buffer, 0, this._buffer.Length, 0,
new AsyncCallback(OnReceive), this._clientSocket);
}
private void OnReceive(IAsyncResult result)
{
Socket clientSocket = (Socket)result.AsyncState;
int bytesRead = clientSocket.EndReceive(result);
this.Recieve();
string data = Encoding.ASCII.GetString(this._buffer, 0, bytesRead);
ThreadPool.QueueUserWorkItem(new WaitCallback(this.HandleDataReceived), data);
}
This doesn't handle situations where there is more data to be received at all. So then I tried this (http://msdn.microsoft.com/en-us/library/bew39x2a.aspx):
private string receivedString = string.Empty;
private void OnReceive(IAsyncResult result)
{
Socket clientSocket = (Socket)result.AsyncState;
int bytesRead = clientSocket.EndReceive(result);
if (bytesRead > 0)
{
receivedString += Encoding.ASCII.GetString(this._buffer, 0, bytesRead);
this.Recieve();
}
else
{
ThreadPool.QueueUserWorkItem(new WaitCallback(this.HandleDataReceived), this.receivedString);
this.receivedString = string.Empty;
}
}
But the problem i'm having with this is that when bytesRead > 0 and I call BeginReceive again I do not get another callback. Did I make some kind of mistake ?
Thanks
In the first code, you have a race condition. Consider:
private void OnReceive(IAsyncResult result)
{
Socket clientSocket = (Socket)result.AsyncState;
int bytesRead = clientSocket.EndReceive(result);
this.Recieve();
string data = Encoding.ASCII.GetString(this._buffer, 0, bytesRead);
ThreadPool.QueueUserWorkItem(new WaitCallback(this.HandleDataReceived), data);
}
You call Receive again, which could overwrite buffer before you send the data to your HandleDataReceived method. I think you want to move that Receive call to after you've converted the data:
private void OnReceive(IAsyncResult result)
{
Socket clientSocket = (Socket)result.AsyncState;
int bytesRead = clientSocket.EndReceive(result);
string data = Encoding.ASCII.GetString(this._buffer, 0, bytesRead);
ThreadPool.QueueUserWorkItem(new WaitCallback(this.HandleDataReceived), data);
this.Recieve();
}
In the second case, you never read 0 bytes because the socket is waiting for data. If there is no data, Socket.Receive will block until there is data available, or until the connection is closed. BeginReceive is waiting for data.

Android retrieve bytes from inputstream

I am trying to retrieve the byte that transferred by the server that has been programmed in c# as follow:
static void Main(String[] args){
Socket sListen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress IP = IPAddress.Parse("10.0.0.92");
IPEndPoint IPE = new IPEndPoint(IP, 4321);
sListen.Bind(IPE);
Console.WriteLine("Service is listening ...");
sListen.Listen(2);
while (true){
Socket clientSocket;
try{
clientSocket = sListen.Accept();
}
catch{
throw;
}
byte[] buffer = ReadImageFile("path to image");
clientSocket.Send(buffer, buffer.Length, SocketFlags.None);
Console.WriteLine("Send success!");
}
}
private static byte[] ReadImageFile(String img){
FileInfo fileinfo = new FileInfo(img);
byte[] buf = new byte[fileinfo.Length];
FileStream fs = new FileStream(img, FileMode.Open, FileAccess.Read);
fs.Read(buf, 0, buf.Length);
fs.Close();
//fileInfo.Delete ();
GC.ReRegisterForFinalize(fileinfo);
GC.ReRegisterForFinalize(fs);
return buf;
}
Above codes works fine when I write a client in the c# and run it in the pc. However I want to retrieve the bytes transferred by the server in the android device.
The android connected to the server successfully but it will not finish its job, basically it will not pass the ‘while loop in the bellow code’. I think there is something wrong with the byte length because it’s never get to ‘-1’.
Android java code (Client):
Socket socket = new Socket("ip", 4321);
InputStream is = socket.getInputStream();
byte[] buffer = new byte[1024];
int read = is.read(buffer);
while(read != -1){
read = is.read(buffer);
}
is.close();
socket.close();
I do appreciate any help in advance,
Thanks,
The client read() method will never return -1 until the server closes the connection. You're not doing that so it never happens.
I don't get the point of your Java code. The read(byte[]) method you are using writes 1024 bytes (or less) in the buffer again and again. You are overwriting your previous buffer content. You probably would like to write the downloaded data to somewhere, like an OutputStream. Example:
Socket socket = new Socket("ip", 4321);
InputStream is = socket.getInputStream();
OutputStream os = ...; // Where to save data, for example, new ByteArrayOutputStream();
copyStreams(is, os);
is.close();
socket.close();
public static void copyStreams(InputStream is, OutputStream os) throws IOException {
byte[] buffer = new byte[1024];
int numBytesRead;
for (;;) {
bytesRead = is.read(buffer);
if (bytesRead <= 0)
break;
os.write(buffer, 0, bytesRead);
}
}

How can i get more than one jpg. or txt file from any folder?

i have two Application to listen network Stream : Server.cs on the other hand; send file Client.cs. But i want to send more files on a stream from any folder. For example. i have C:/folder whish has got 3 jpg files. My client must run. Also My server.cs get files on stream:
Client.cs:
private void btn_send2_Click(object sender, EventArgs e)
{
string[] paths= null;
paths= System.IO.Directory.GetFiles(#"C:\folder" + #"\", "*.jpg", System.IO.SearchOption.AllDirectories);
byte[] Dizi;
TcpClient Gonder = new TcpClient("127.0.0.1", 51124);
FileStream Dosya;
FileInfo Dos;
NetworkStream Akis;
foreach (string path in paths)
{
Dosya = new FileStream(path , FileMode.OpenOrCreate);
Dos = new FileInfo(path );
Dizi = new byte[(int)Dos.Length];
Dosya.Read(Dizi, 0, (int)Dos.Length);
Akis = Gonder.GetStream();
Akis.Write(Dizi, 0, (int)Dosya.Length);
Gonder.Close();
Akis.Flush();
Dosya.Close();
}
}
Also i have Server.cs
void Dinle()
{
TcpListener server = null;
try
{
Int32 port = 51124;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
server = new TcpListener(localAddr, port);
server.Start();
Byte[] bytes = new Byte[1024 * 250000];
// string ReceivedPath = "C:/recieved";
while (true)
{
MessageBox.Show("Waiting for a connection... ");
TcpClient client = server.AcceptTcpClient();
MessageBox.Show("Connected!");
NetworkStream stream = client.GetStream();
if (stream.CanRead)
{
saveFileDialog1.ShowDialog();
// burası degişecek
string pathfolder = saveFileDialog1.FileName;
StreamWriter yaz = new StreamWriter(pathfolder);
string satir;
StreamReader oku = new StreamReader(stream);
while ((satir = oku.ReadLine()) != null)
{
satir = satir + (char)13 + (char)10;
yaz.WriteLine(satir);
}
oku.Close();
yaz.Close();
client.Close();
}
}
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
finally
{
// Stop listening for new clients.
server.Stop();
}
Console.WriteLine("\nHit enter to continue...");
Console.Read();
}
Please look Client.cs: icollected all files from "c:\folder"
paths= System.IO.Directory.GetFiles(#"C:\folder" + #"\", "*.jpg", System.IO.SearchOption.AllDirectories);
My Server.cs how to get all files from stream?
It's not a typical way of doing things.
Usually you would write a single file in a single stream and repeat the process for multiple files. You risk data corruption this way as you'll have to place some kind of marker in the stream to know where to split it.
The easiest way is to use multiple sockets, one for commands and one (or more) for sending files.
The below code have NOT been tested, just wrote it up to show what I mean. It's multithreaded and can receive multiple files from the same client, just call sendfiles multiple times in the client.
You might want to add error/exception handling if you decide to finish the code.
Server.cs
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Test2
{
public class Server
{
private readonly TcpListener _listener = new TcpListener(1234);
public void Start()
{
_listener.BeginAcceptTcpClient(OnClient, null);
}
private void OnClient(IAsyncResult ar)
{
// End async accept and start wait for a new connection again
TcpClient client = _listener.EndAcceptTcpClient(ar);
_listener.BeginAcceptTcpClient(OnClient, null);
// Let's start receiving files from the accepted client.
var context = new Context {Client = client, Buffer = new byte[8196]};
client.GetStream().BeginRead(context.Buffer, 0, context.Buffer.Length, OnReceive, context);
}
/// <summary>
/// Got some stuff from a client
/// </summary>
/// <param name="ar"></param>
private void OnReceive(IAsyncResult ar)
{
// got a file command
var context = (Context) ar.AsyncState;
int bytesRead = context.Client.GetStream().EndRead(ar);
string cmd = Encoding.UTF8.GetString(context.Buffer, 0, bytesRead);
string[] parts = cmd.Split(';');
string command = parts[0];
// want to send another file
if (command == "sendfile")
{
// context info for receiving files
var client = new FileClient();
client.FileName = parts[1];
client.Size = long.Parse(parts[2]);
client.FileStream = new FileStream("C:\\" + client.FileName, FileMode.CreateNew, FileAccess.Write);
// startup listener where we are going to receive the file.
var listener = new TcpListener(IPAddress.Any, 0); // get a kernelassigned number
client.Listener = listener;
listener.Start();
listener.BeginAcceptTcpClient(OnFileSocket, client);
// send reply
var ep = (IPEndPoint) listener.LocalEndpoint;
byte[] reply = Encoding.UTF8.GetBytes(ep.Port.ToString());
context.Client.GetStream().Write(reply, 0, reply.Length);
}
}
// Receiving the actual files.
private void OnFileSocket(IAsyncResult ar)
{
var client = (FileClient) ar.AsyncState;
client.Socket = client.Listener.EndAcceptTcpClient(ar);
var buffer = new byte[8192];
client.Buffer = buffer;
client.Socket.GetStream().BeginRead(buffer, 0, buffer.Length, OnReceiveFile, client);
}
private void OnReceiveFile(IAsyncResult ar)
{
var client = (FileClient) ar.AsyncState;
int bytesRead = client.Socket.GetStream().EndRead(ar);
client.Received += bytesRead;
client.FileStream.Write(client.Buffer, 0, bytesRead);
// recieved complete file, disconnect and exit.
if (client.Received == client.Size)
{
client.FileStream.Close();
client.Socket.Close();
return;
}
client.Socket.GetStream().BeginRead(client.Buffer, 0, client.Buffer.Length, OnReceiveFile, client);
}
#region Nested type: Context
private class Context
{
public byte[] Buffer;
public TcpClient Client;
}
#endregion
#region Nested type: FileClient
private class FileClient
{
public byte[] Buffer;
public string FileName;
public FileStream FileStream;
public TcpListener Listener;
public long Received;
public long Size;
public TcpClient Socket;
}
#endregion
}
}
Client.cs
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Test2
{
internal class Client
{
private readonly IPAddress _server;
private readonly TcpClient _tcpClient = new TcpClient();
public Client(IPAddress server)
{
_server = server;
_tcpClient = new TcpClient();
}
public void Connect()
{
_tcpClient.Connect(new IPEndPoint(_server, 1234));
}
// asks server on which port the file should be sent.
private int RequestPort(string fileName, long length)
{
// lock tpcClient for each request, so we dont mix up the responses.
lock (_tcpClient)
{
// send request
byte[] bytes = Encoding.UTF8.GetBytes("sendfile;" + fileName + ";" + length);
_tcpClient.GetStream().Write(bytes, 0, bytes.Length);
// get reply
var buffer = new byte[1024];
int bytesRead = _tcpClient.GetStream().Read(buffer, 0, buffer.Length);
string reply = Encoding.UTF8.GetString(buffer, 0, bytesRead);
// error message or port?
int port;
if (!int.TryParse(reply, out port))
throw new InvalidOperationException("Server sent an error:" + reply);
return port;
}
}
public void SendFiles(string[] fileNames)
{
// Use a buffer to not preserve memory (instead of reading whole file into memory)
var buffer = new byte[8192];
foreach (string fileName in fileNames)
{
using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
// Send on commandchannel that we want to send a file.
int filePort = RequestPort(Path.GetFileName(fileName), fileStream.Length);
var client = new TcpClient(new IPEndPoint(_server, filePort));
NetworkStream stream = client.GetStream();
// repeat until there are no more bytes to read.
int bytesRead = fileStream.Read(buffer, 0, buffer.Length);
while (bytesRead > 0)
{
stream.Write(buffer, 0, bytesRead);
bytesRead = fileStream.Read(buffer, 0, buffer.Length);
}
stream.Close();
client.Close();
}
}
}
}
}

Categories