Load image over socket - c#

I'm currently receiving text:
private void ReceiveCallback(IAsyncResult AR)
{
try
{
int received = _clientSocket.EndReceive(AR);
//string text = Encoding.ASCII.GetString(_buffer);
Array.Resize(ref _buffer, received);
//AppendToTextBox(text);
Array.Resize(ref _buffer, _clientSocket.ReceiveBufferSize);
_clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
How can I read an image, instead of text?

You'd probably want to wait to receive the entire thing, and then:
using(var ms = new MemoryStream(entireBuffer)) {
var image = Image.FromStream(ms);
// Go ahead and put it in a PictureBox now
}

Related

The input stream is not a valid binary format Tcp

I have 2 method they look and work very similarly. Dont know why first method work but second dont. Secound throw Exeption "The input stream is not a valid binary format Tcp" This method send object by tcp from client to server and from server to client.
Can sameone tell me what am I doing wrong?
public static void SendComput(NetworkStream stream)
{
string id = "1";
Byte[] datasend = System.Text.Encoding.ASCII.GetBytes(id);
BinaryFormatter formatter = new BinaryFormatter();
stream.Write(datasend, 0, datasend.Length);
Console.WriteLine("Sent: {0}", id);
while (true)
{
try
{
var data = new Byte[256];
String response = String.Empty;
Int32 bytes = stream.Read(data, 0, data.Length);
response = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}", response);
}
catch (Exception e)
{
throw;
}
try
{
var t = GetComputeUnitsPerf();
var t2 = new Comp();
t2.ComputeTime = (uint)t.TimeMilisceoncd;
t2.DateCheck = t.Date;
t2.Id = Int32.Parse(id);
formatter.Serialize(stream,t2);
Console.WriteLine("Sent: {0}, {1}, {2}", t2.Id , t2.ComputeTime, t2.DateCheck);
Thread.Sleep(100);
}
catch (Exception e)
{
throw;
}
}
}
And server:
public void HandleDeivce3(Object obj)
{
TcpClient client = (TcpClient)obj;
var stream = client.GetStream();
Byte[] bytes = new Byte[256];
int i = 0;
string data = null;
BinaryFormatter formatter = new BinaryFormatter();
Task.Run(() =>
{
string hex = BitConverter.ToString(bytes);
data = Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
while (true)
{
Thread.Sleep(10000);
Byte[] reply = System.Text.Encoding.ASCII.GetBytes("Send");
stream.Write(reply, 0, reply.Length);
Console.WriteLine("Send");
Thread.Sleep(200);
try
{
if (stream.CanRead)
{
var dataGet = (Comp)formatter.Deserialize(stream);
//Console.WriteLine("Sent: {0}, {1}, {2}", dataGet.Id, dataGet.ComputeTime, dataGet.DateCheck);
Console.WriteLine(dataGet.Id);
}
}
catch (Exception e)
{
throw;
}
}
});
}
I add [Serializable] to Comp class.

C# async socket file transfer

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();
}
}

tcp having trouble connecting c#

I'm having trouble getting my Sender thread to connect to my Receiver thread. Here's my code below (I'm a novice when it comes to socket programming so if you know a better of sending images over sockets please let me know):
Sender thread:
public void SendSS()
{
try
{
while (!mainFrm.ssStop)
{
TcpClient ssTcpClient = new TcpClient();
ssTcpClient.Connect(mainFrm.contactIP, 1500);
if (ssTcpClient.Connected)
{
Image screenShotBMP = GrabScreen();
NetworkStream ns = ssTcpClient.GetStream();
memStream = new MemoryStream();
screenShotBMP.Save(memStream, ImageFormat.Png);
byte[] bytesToSend = memStream.ToArray(); ;
ns.Write(bytesToSend, 0, bytesToSend.Length);
ns.Flush();
screenShotBMP.Dispose();
ns.Close();
memStream.Close();
ssTcpClient.Close();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "frmVoiceChat-SendSS()", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Receiver thread:
public void ReceiveSS()
{
try
{
TcpListener ssTcpListener = new TcpListener(IPAddress.Any, 1500);
while (!mainFrm.ssStop)
{
ssTcpListener.Start();
TcpClient tcpReceiver = ssTcpListener.AcceptTcpClient();
//TcpClient tcpReceiver = new TcpClient();
ssTcpListener.AcceptTcpClient();
//tcpReceiver.Connect(mainFrm.contactIP, 1500);
if (tcpReceiver.Connected)
{
labelText("Connected!!!");
//NetworkStream receivedNs = tcpReceiver.GetStream();
NetworkStream receivedNs = new NetworkStream(tcpReceiver.Client);
//ssTcpListener.Server.Receive();
//byte[] imageBytes = new byte[tcpReceiver.ReceiveBufferSize];
//receivedNs.Read(imageBytes, 0, imageBytes.Length);
//MemoryStream receivedMs = new MemoryStream(imageBytes);
//receivedNs.CopyTo(receivedMs);
//Image image = Image.FromStream(receivedNs); // ArgumentException: Parameter is not valid exception here.
pbScreenShare.Image = new Bitmap(receivedNs);
receivedNs.Close();
tcpReceiver.Close();
ssTcpListener.Stop();
//image.Dispose();
//receivedMs.Close();
}
else
{
labelText("Not Connected!!!");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "frmVoiceChat-ReceiveSS()", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
You call AcceptTcpClient() twice. The second call will wait for a connection and block the rest of the code from executing. Please clean up your code.

Sending files from Android client to c# server, breaks before reading whole file

c# code
private MemoryStream Read() {
NetworkStream clientStream = _client.GetStream();
MemoryStream messageStream = new MemoryStream();
var inbuffer = new byte[65535];
if(clientStream.CanRead) {
do {
int bytesRead = clientStream.Read(inbuffer,0,inbuffer.Length);
messageStream.Write(inbuffer, 0, bytesRead);
messageStream.Flush();
Debug.Print(messageStream.Length + " added " + bytesRead);
} while(clientStream.DataAvailable); // GOES BEYOND HERE, EVEN THOUGH THERE'S MORE DATA
}
messageStream.Position = 0;
return messageStream;
}
android code
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode == RESULT_OK){
if(requestCode == ATTACH_FILE_REQUEST){
writeToSocket("<FILE>generic.jpeg");
InputStream input = null;
String filePath = data.getData().getPath().toString();
try {
input = getContentResolver().openInputStream(data.getData());
BufferedInputStream bufferedInputStream = new BufferedInputStream(input);
byte[] bytes = new byte[65535];
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
while((bufferedInputStream.read(bytes)) != -1){
byteArray.write(bytes, 0, bytes.length);
}
socketNetworkHelper.writeFile(byteArray.toByteArray());
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
Toast.makeText(this, "Error in file selection", Toast.LENGTH_LONG).show();
} catch (IOException e2){
e2.printStackTrace();
Toast.makeText(this, "Input/Output Error", Toast.LENGTH_LONG).show();
}
}
}
}
In SocketNetworkHelper.java which has a socket connected:
public void writeFile(byte[] buffer) {
try {
socket.getOutputStream().write(buffer);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
The question is: How can I get the whole file?
You could also send the filesize as a parameter
private MemoryStream Read(int filesize) {
NetworkStream clientStream = _client.GetStream();
MemoryStream messageStream = new MemoryStream();
var inbuffer = new byte[filesize];
if (clientStream.CanRead) {
int totalBytesRead = 0;
do {
int bytesRead = clientStream.Read(inbuffer, 0, inbuffer.Length);
totalBytesRead += bytesRead;
messageStream.Write(inbuffer, 0, bytesRead);
messageStream.Flush();
} while (totalBytesRead < filesize);
}
messageStream.Position = 0;
return messageStream;

Proper sending and receiving via C# sockets?

I'm attempting to create a remote desktop server and client using C#. The server captures the screen and then sends it to the client via a socket. I'm using the code below although it only displays a part of the jpeg image on the client. I think this is because the image is sent in multiple packets and at the moment the code only reads the one packet and displays it. Can anyone explain how I would change my code so it receives multiple packets (the whole image) before displaying it.
Server code:
Socket serverSocket;
Socket clientSocket;
public Form1()
{
InitializeComponent();
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
serverSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 8221);
serverSocket.Bind(ipEndPoint);
serverSocket.Listen(4);
//Accept the incoming clients
serverSocket.BeginAccept(new AsyncCallback(OnAccept), null);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Stream Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
Rectangle bounds = new Rectangle(0, 0, 1280, 720);
Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size);
}
System.IO.MemoryStream stream = new System.IO.MemoryStream();
ImageCodecInfo myImageCodecInfo;
System.Drawing.Imaging.Encoder myEncoder;
EncoderParameter myEncoderParameter;
EncoderParameters myEncoderParameters;
myEncoderParameters = new EncoderParameters(1);
myImageCodecInfo = GetEncoderInfo("image/jpeg");
myEncoder = System.Drawing.Imaging.Encoder.Quality;
myEncoderParameter = new EncoderParameter(myEncoder, 40L);
myEncoderParameters.Param[0] = myEncoderParameter;
bitmap.Save(stream, myImageCodecInfo, myEncoderParameters);
byte[] imageBytes = stream.ToArray();
stream.Dispose();
clientSocket.Send(imageBytes);
timer1.Start();
}
As you can see, I'm using a timer which has the interval set to 30 for sending the image bytes.
Client code:
public Socket clientSocket;
byte[] byteData = new byte[2048];
MemoryStream ms;
public Form1()
{
InitializeComponent();
backgroundWorker1.RunWorkerAsync();
this.DoubleBuffered = true;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
clientSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse("MY EXTERNAL IP HERE"), 8221);
//Connect to the server
clientSocket.BeginConnect(ipEndPoint,
new AsyncCallback(OnConnect), null);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "SGSclient",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
private void OnConnect(IAsyncResult ar)
{
try
{
//Start listening to the data asynchronously
clientSocket.BeginReceive(byteData,
0,
byteData.Length,
SocketFlags.None,
new AsyncCallback(OnReceive),
null);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Stream Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void OnReceive(IAsyncResult ar)
{
try
{
int byteCount = clientSocket.EndReceive(ar);
ms = new MemoryStream(byteData);
using (BinaryReader br = new BinaryReader(ms))
{
this.BackgroundImage = Image.FromStream(ms).GetThumbnailImage(this.ClientRectangle.Width, this.ClientRectangle.Height, null, IntPtr.Zero);
}
}
catch (ArgumentException e)
{
//MessageBox.Show(e.Message);
}
clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnReceive), null);
}
The client is meant to receive the image and then display it on the form's background.
You need to add application level protocol to your socket communications.
Add a header to all messages sent. The header contains the count of bytes that follow. It is simpler code and performs better to have a byte count than to kludge a termination sequence.
The client then does two sets of reads:
1) Read for the number of bytes that are known to be in any header.
2) After extracting the byte count from the header, loop reading until you get the indicated byte count.
A must-read article for all people who are writing socket communications: http://nitoprograms.blogspot.com/2009/04/message-framing.html
From that article: Repeat this mantra three times: "TCP does not operate on packets of data. TCP operates on streams of data."
I have previously answered a similar question, and provided a fully working example that I think does exactly what you are trying to do. See: transferring a screenshot over a TCP connection
You must set a delimiter at the end of your image, some set of bytes that will sinalize the server that the image has ended. It's also known as end of file (EOF) or end of message. TCP won't split the image into logical packets for your app, so you must write your own control of information.
The logic would be similar to this:
CLIENT
byte[] EndOfMessage = System.Text.Encoding.ASCII.GetBytes("image_end");
byte[] ImageBytes = GetImageBytes();
byte[] BytesToSend = new byte[EndOfMessage.Length + ImageBytes.Length];
Array.Copy(ImageBytes, 0, BytesToSend);
Array.Copy(EndOfMessage, 0, BytesToSend, ImageBytes.Length, EndOfMessage.Length);
SendToServer(BytesToSend);
SERVER
byte[] EndOfMessage = System.Text.Encoding.ASCII.GetBytes("image_end");
byte[] ReceivedBytes;
while(!IsEndOfMessage(ReceivedBytes, EndOfMessage ))
{
//continue reading from socket and adding to ReceivedBytes
}
ReceivedBytes = RemoveEndOfMessage(ReceivedBytes, EndOfMessage );
PrintImage(ReceivedBytes);
I'm at work right now and I can't provide a full running example, I'm sorry.
Regards
Support methods:
private bool IsEndOfMessage(byte[] MessageToCheck, byte[] EndOfMessage)
{
for(int i = 0; i++; i < EndOfMessage.Length)
{
if(MessageToCheck[MessageToCheck.Length - (EndOfMessage.Length + i)] != EndOfMessage[i])
return false;
}
return true;
}
private byte[] RemoveEndOfMessage(byte[] MessageToClear, byte[] EndOfMessage)
{
byte[] Return = new byte[MessageToClear.Length - EndOfMessage.Length];
Array.Copy(MessageToClear, Return, Return.Length);
return Return;
}
Again, I couldn't test them, so you may find some bugs.

Categories