How to transfer a file by socket PHP to C# [duplicate] - c#

This question already has answers here:
How to receive a file over TCP which was sent using socket.FileSend Method
(2 answers)
Closed 7 years ago.
Hi after a lot of research i didn't found a solution to my case
I have a C# socket server what's is running on my server and i need to transfer files to it by Socket from my website that's in PHP.
What i have now ?
Php part:
$file = array('file' => Input::file('file'));
$fp = stream_socket_client("tcp://localhost:9192", $error_number, $error_string);
if ( !$fp ) {
echo "$error_number ($error_string)\n";
} else {
fwrite($fp, $file['file']);
}
fclose($fp);
C# Socket Server:
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer, 0, bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1)
{
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content);
// Echo the data back to the client.
Send(handler, content);
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
When i try to make the connection the C# instantly refuses it what i'm doing wrong ?
I'm using Laravel 5 on PHP part.

I found a solution in this question:
How to receive a file over TCP which was sent using socket.FileSend Method
Sorry for waste your time :)

Related

EndReceive in Async Socket without strings

I'm following this example about the creation of an async tcp listener in C#.
MSDN Example
I see that all data is encoded as string to check for message completeness. More precisely, every message sent is already a string, which we append the 'EOF' char to for string termination.
The server side part i'm talking about is in this snippet:
public static void ReadCallback(IAsyncResult ar) {
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject) ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0) {
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer, 0, bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1) {
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content );
// Echo the data back to the client.
Send(handler, content);
} else {
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
Is there a way, as i usually do with TcpListener/TcpClient classes, to check if received bytes are available on the socket?
I mean something like this:
private void HandleClientConnection(TcpClient client)
{
NetworkStream clientStream = client.GetStream();
MemoryStream memoryStream = new MemoryStream();
while (true)
{
int read = clientStream.ReadByte();
if (read != -1)
{
memoryStream.WriteByte((byte)read);
}
else
{
break;
}
}
}
I'm aware that i probably misunderstood this example, or at least the Begin/End part and the "legacy" async pattern. But this is my goal, do you know some way to get it working without involving strings?
You said : "Is there a way to check if received bytes are available on the socket?"
In general 'EndReceive' will block the thread until data is available. So you don't need to do anything because 'EndReceive' is doing all the job for you.
'bytesRead' is an int that shows you how much data you have received.
a quote from docs.microsoft
The EndReceive method will block until data is available.1
But if you are using a SYNC socket (which you are not) then it's another topic.

Async socket - Duplex communication with permanent sockets in c#

I'm trying to do asynchronous socket communication, and want the server to keep a list of all connected sockets, so he can broadcast messages to them.
First I took the examples from msdn Asynchronous Socket Server and altered them a little so they don't close the sockets. (just removed the .shutdown and .Close commands)
But doing so, seems to cause the client to hang in the "receiving part".
Here are the changes I made to the msdn examples:
Client:
only changed ReceiveCallback() so it stays in an endless receiving loop:
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
// All the data has arrived; put it in response.
if (state.sb.Length > 1)
{
response = state.sb.ToString();
Console.WriteLine(state.sb.ToString());
}
// Signal that all bytes have been received.
receiveDone.Set();
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
The Server:
just commented out the lines that close the socket:
//handler.Shutdown(SocketShutdown.Both);
//handler.Close();
Later i planed to keep a List of Sockets so i can send Messages to them, but it already fails here.
I'm greatfull for any hints, also I would like to hear your opinion on using this tenique for a server that has to serve at max 100 clients, which could send a request any 2 seconds. (The communication should be both ways, so that the client and the Server can send a Message at any time without waiting for a Message to respond to).
Thank you and good evening
Martin
EndReceive only returns 0 when the socket is closed. Your clients will never set the receiveDone handle because the server never closes the socket. The callback is called when data is received OR when the connection is terminated.
You need to detect the end of message (like the example you linked too).
eg. (Modified version of the code you linked)
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1) {
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content );
// Echo the data back to the client.
Send(handler, content);
{ // NEW
// Reset your state (persist any data that was from the next message?)
// Wait for the next message.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
} else {
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}

TcpClient - An existing connection was forcibly closed by the remote host

The Info
I have been developing a web http server in c# and decided to add a remote console feature. The console can be used from any location and uses a TcpListener (web server) and a TcpClient (remote console) to send commands and functions through.
The Code
This is what my server looks like:
TcpListener consoleListener = new TcpListener(consolePort);
consoleListener.Start();
byte[] bytes = new Byte[256];
string data = null;
while (true)
{
TcpClient client = consoleListener.AcceptTcpClient();
data = null;
byte[] msg = { 0 };
int i;
while ((i = client.GetStream().Read(bytes, 0, bytes.Length)) != 0)
{
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
if (data == "shutdown")
{
//Server shutdown logic.
}
//Other commands here...
else
{
msg = Encoding.ASCII.GetBytes("Invalid command. Type 'help' or '?' to get a list of commands.");
}
client.GetStream().Write(msg, 0, msg.Length); //sends return message to console
}
client.Close(); //closes connection between client and server after EVERY command. Connection is reopened when a new command is sent.
}
Note - The server is run on a separate thread to both the webserver and main console application thread.
This is my client:
public static string Communicate(string text)
{
try
{
TcpClient client = new TcpClient(ip, port); //initializes tcpclient (ip and port are correct)
byte[] data = System.Text.Encoding.ASCII.GetBytes(text); //converts text to bytes for stream writing
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent data: " + text);
data = new Byte[256];
string responseData = String.Empty; //initializes responsData string
Int32 bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
client.Close();
return responseData; //returns what server writes
}
catch (Exception ex)
{
return "An error occured\n" + ex.ToString();
}
}
The Problem
I can send one command to the server with a successful return. However, when I try and send another command, the server throws the error below:
System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
--- End of inner exception stack trace ---
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at ---.Server.ConsoleListener() in X:\Users\---\Documents\Visual Studio 2013\Projects\---\---\Program.cs:line x
I know it is not firewall or administrator elevation problems as I can send one command through successfully. It is only on the second command sent that it throws this error.
Here is a screenshot describing the problem:
EDIT: By doing a little research, I found that the problem is most likely a result of a small error in my for loop. However, I do not know any way of fixing this as I do not know the exact problem :). Please help me identify it so I can fix it.
Thanks again
It seems that your client closes the connection after one message.
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
client.Close();
return responseData; //returns what server writes
If you want to persist the connection you should have a loop on the client similar to the one you have on the server. If you want to establish a new connection every time you should close the stream gracefully on the server and not have a loop like this. You will still need to loop in case the message is longer or you need to specify max length for the command.
I don't know if you fixed your issue or not but I guess you should post your workaround at least so others can check it.
I don't fully understand your issue but I had the same exception, but mine was triggered while the client disconnected and server was trying to read the stream (networkStream).
I had a single command for reading
networkstream.Read(mybuffer, 0, mybuffer.length);
As the checked answer suggested I changed that for:
do
{
byte[] buff = new byte[1];
networkstream.Read(buff, 0, 1);
myreceivedbuff.Add(buff);
} while (networkstream.DataAvailable)
this also produced the issue while client disc, so I had to do this
do
{
byte[] buff = new byte[1];
try
{
networkstream.Read(buff, 0, 1);
}
catch(exception ex)
{
throw new exception("The dam client disconnected in the middle of a transaction.");
}
myreceivedbuff.Add(buff);
} while (networksteam.DataAvailable)
I had to do this since it doesn't matter if its on a client or a server the exception is the same. host disconnection meanwhile my exception was CLIENT disconnection and this generic message misguided me to the solution.
Sorry if the code is not pasted from vs but I typed here so fix the capitalization so it can compile.
Hope this helps someone.
I had same solution. it is usually happens if client is disconnected. Solution from Alex RG is not working unfortunately. you will get another exception. Best solutions is described here by Microsoft
you need to check using CanRead
TcpClient tcpClient = new TcpClient ();
// Uses the GetStream public method to return the NetworkStream.
NetworkStream netStream = tcpClient.GetStream ();
if (netStream.CanRead)
{
// Reads NetworkStream into a byte buffer.
byte[] bytes = new byte[tcpClient.ReceiveBufferSize];
// Read can return anything from 0 to numBytesToRead.
// This method blocks until at least one byte is read.
netStream.Read (bytes, 0, (int)tcpClient.ReceiveBufferSize);
// Returns the data received from the host to the console.
string returndata = Encoding.UTF8.GetString (bytes);
Console.WriteLine ("This is what the host returned to you: " + returndata);
}
else
{
Console.WriteLine ("You cannot read data from this stream.");
tcpClient.Close ();
// Closing the tcpClient instance does not close the network stream.
netStream.Close ();
return;
}

Close BufferedStream without TcpClient disconnect?

I am trying to send image via TcpClient and BufferedStream. The problem is that i cant send the data without disconnecting the TcpClient.
Send data:
while ((bytesread = bufferedinput.Read(buffer, 0, sizeBuffer)) > 0)
{
//Sending data
bufferedoutput.Write(buffer, 0, bytesread);
}
Receive data:
while ((bytesread = bufferedinput.Read(buffer, 0, buffsize)) > 0)
{
bufferedoutput.Write(buffer, 0, bytesread);
}
where :
NetworkStream serverStream = client.GetStream();
and BufferedStream bufferedoutput = new BufferedStream(serverStream);
The problem is that i must cast bufferedoutput.Close(); in the client side to get the data received by the server, but this disconnects my client, which is a problem. Any suggestions?
It is evident that by closing NetworkStream object associated with a TcpClient object, disconnects the client. Since TCP is a stream based protocol, you can do only one of two thing, either 1.] use networkstream.readtimeout to disconnect if no data is available till the readtimeout, OR 2.] devise a protocol to tell the receiver about the length of data, sender is willing to send, and read only that length of bytes.
Have you tried just bufferedoutput.Flush() instead?

How to determine the end of a file transfer (data) from the client to the server (Socket)

Simple situation:
The client on a Socket sends a pieces(e.g., 256 byte) of the file (data) in the format byte []to the server. The server receives the data asynchronously.
How to determine when a file (data) is transmitted completely? (Server-side)
Here's the code on server-side responsible for receiving data
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
BinaryWriter writer = new BinaryWriter(File.Open(#"D:\test.png", FileMode.Append));
writer.Write(state.buffer, 0, bytesRead);
writer.Close();
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket!",
bytesRead);
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
Is there a method that allows to make the some following?
if (bytesRead > 0)
{
....
if(state.buffer!=end of receive)
{
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
Or, I may to try add some information to the this byte[] object (e.g., some string with <EOF> tag)
but I must to analyse this info on each step.
May I do this check more simple and how? Or use another way ...
The only way to do it is to sent a header (of specific size) in front of every message. So, the each message should consist of header and body. The data stream should look like this:
[HEADER][BODY][HEADER][SOME BIGGER BODY][HEADER][SOME EXTRA BIG BODY]
As I said, the header should be of specific size and should contain some custom service fields inlcuding the size of the message's body in bytes. In your case the header could contain only body size, i.e. int value (4 bytes). The receive process should look like this:
Receive 4 bytes (header);
Retrieve body size from header (just convert header to int);
Receive the number of bytes specified in header (i.e. receive message body);
Handle message body;
Go to 1.
I know, it may seem complicated for you, but it is the common way to do it. But you can simplify the code by using Rx library. After implementing some extensions methods for socket (WhenReadExact, the implementation could easily be found over Internet, for example here), the code will look like this:
var whenFileReceived = from header in socket.WhenReadExact(4)
let bodySize = BitConverter.ToInt32(header)
from body in socket.WhenReadExact(bodySize)
select body;
whenFileReceived.Subscribe(
file =>
{
// Handle file here
});

Categories