Send image using TCP Socket Client App in Windows Phone - c#

I'm trying to develop a simple TCP Client Application for Windows Phone.
On the server side, I'm using a simple C# Server Application which accepts the connection and then saves the file.
I saw an example on MSDN (for the client app, http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202858(v=vs.105).aspx).
But it only sends strings and I want to send files (pictures) from the client to the picture.
This is a server side code snippet which accepts the file sent from the client:
if (Listener.Pending())
{
client = Listener.AcceptTcpClient();
netstream = client.GetStream();
Status = "Connected to a client\n";
result = MessageBox.Show(message, caption, buttons);
if (result == System.Windows.Forms.DialogResult.Yes)
{
string SaveFileName = string.Empty;
SaveFileDialog DialogSave = new SaveFileDialog();
DialogSave.Filter = "All files (*.*)|*.*";
DialogSave.RestoreDirectory = true;
DialogSave.Title = "Where do you want to save the file?";
DialogSave.FileName = "sample.txt";
if (DialogSave.ShowDialog() == DialogResult.OK)
SaveFileName = DialogSave.FileName;
if (SaveFileName != string.Empty)
{
int totalrecbytes = 0;
FileStream Fs = new FileStream(SaveFileName, FileMode.OpenOrCreate, FileAccess.Write);
while ((RecBytes = netstream.Read(RecData, 0, RecData.Length)) > 0)
{
Fs.Write(RecData, 0, RecBytes);
totalrecbytes += RecBytes;
}
Fs.Close();
}
netstream.Close();
client.Close();
}
}
Now, the problem that I'm facing is that when I send the string from the phone, the server successfully acknowledges the connection and prompts to save the file. But, when I save the file and open it, the file is blank.
To check if the server is working properly, I made a simple C# client app (on Windows, not phone) and sent a file using that. And, it was saved successfully with all the contents intact.
Please help me.
Problems:
First, the string sent by the phone is acknowledged by the server but cannot be saved to a file.
Second, how to send an image from the phone (client)?
I thought of converting the image into base64 string and then sending the string to the server.
But, I don't know how to convert an image to a base64 string on Windows Phone.
Please help me.
Thanks in advance!

You could certainly write all of this yourself but have you possibly considered using a library to help save time? If so then checkout networkcomms.net, in particular a tutorial on sending non-primitive objects, using an image in the example, here.
Disclaimer: I'm a developer for this library.

Convert imageStream into memory Stream. Then convert to byte then to Base 64.
Stream imgStream = readImgFromFile(filename);
var memoryStream = new MemoryStream(imgStream);
byte[] result = memoryStream.ToArray();
base64 = System.Convert.ToBase64String(result);

Related

Redirecting an Audio Stream to avoid CORS - C#

I need to redirect an audio stream to avoid CORS in order to use AudioContext() for visualizations.
Instead of using the original stream url, I'd point the player to "mysite.com/stream/", which would intercept the stream and feed it to the player.
I really don't know what I'm doing in this case, which should be obvious from my attempt below. Thanks to anyone for some help.
System.Net.HttpWebRequest web = (System.Net.HttpWebRequest)System.Net.WebRequest.Create("https://ssl.geckohost.nz/proxy/caitlinssl?mp=/stream");
Response.ContentType = "audio/aac";
char[] buffer = new char[8192];
byte[] buffer_bytes = new byte[8192];
using (System.Net.HttpWebResponse web_resp = (System.Net.HttpWebResponse)web.GetResponse())
{
using (System.IO.Stream stream_web = web_resp.GetResponseStream())
{
//stream_web.CopyTo(Response.OutputStream);
using (System.IO.StreamReader stream_rdr = new System.IO.StreamReader(stream_web))
{
for (var i = 0; i < 100; i++)
{
stream_rdr.Read(buffer, 0, 8192);
Response.Write(buffer);
Response.Flush();
}
}
}
}
The solution I found was originally created for use with NAudio to play a remote MP3 file, but I was able to repurpose it for my needs. There are probably better ways, but this works.
Play audio from a stream using C#
Edit: It seems that the connection is dropped server to server, but I'm not positive. IIS will not send "Connection: keep-alive" to the client, however it is being sent to the client by the original stream. Tried adding KeepAlive = true to the WebRequest, and changing the protocol version to HTTP 1.0 to keep the server to server connection alive with no joy.
string url = "https://ssl.geckohost.nz/proxy/caitlinssl?mp=/stream";
Response.ContentType = "audio/aac";
using (Stream stream = WebRequest.Create(url).GetResponse().GetResponseStream())
{
byte[] buffer = new byte[32768];
int read;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
Response.OutputStream.Write(buffer, 0, read);
Response.Flush();
}
}
Conclusion: It seems that in this case it is not possible with IIS to persist the connection server to server, as far as I was able to find. I'm not worried about scalability as this is a personal project for a user of 1. The solution I ended up with is to start capturing the stream with ffmpeg on click, transcode it to flac/mkv, and use a variation of the above to read the file while it's being written and feed it to the player (WPF WebView [IE/Edge]).

Network Stream does not Write data

I'm trying to read and write data from a TCP Server with the following code.
cs1.witsStream = new NetworkStream(cs1.witsClient.Client);
Byte[] receive_bytes = new Byte[256];
Int32 bytes = cs1.witsStream.Read(receive_bytes, 0, receive_bytes.Length);
cs1.tempData = System.Text.Encoding.ASCII.GetString(receive_bytes, 0, bytes);
d_in.Text = cs1.tempData;
if (cs1.witsStream.CanWrite == true)
{
string send_data = "0105000";
byte[] send_bytes = Encoding.ASCII.GetBytes(send_data);
cs1.witsStream.Write(send_bytes,0,send_bytes.Length);
}
cs1.witsStream.Close();
The reading part works fine with no error. But the writer fails to work. There is no exception thrown.
Already tried: Flush stream before write, Use another stream to write and WriteAsync, WriteByte. All fail to write data.
Also tried to send data from another program to the said server and it reads fine, to isolate any server side issue.
Any ideas would be appreciated.

How to read the content of file from port

I am in needed to use the text data in to a program when someone prints a file.
I have basic ideas about the TCP/IP client and listener programming.
Already I could send and receive txt files between two machines.
But how to receive the file contents if the files were in docx,xlx,pdf or any other format?
My requirement is,
I wanted to use the contents (texts) of a file in to another program when someone prints a file.
Please suggest me if there is some alternative ways to do it.
Thank in advance.
Since you haven't posted any code I'll write the code part in "my way" but you should have a bit of understanding after reading this.
First on both of the ends ( client and server ) you should apply unified protocol which will describe what data you're sending. Example could be:
[3Bytes - ASCII extension][4Bytes - lengthOfTheFile][XBytes - fileContents]
Then in your sender you can receive data according to the protocol which means first your read 3 bytes to decide what format file has, then you read 4 bytes which will basically inform you how large file is incomming. Lastly you have to read the content and write it directly to the file. Example sender could look like this :
byte[] extensionBuffer = new byte[3];
if( 3 != networkStream.Read(extensionBuffer, 0, 3))
return;
string extension = Encoding.ASCII.GetString(extensionBuffer);
byte[] lengthBuffer = new byte[sizeof(int)];
if(sizeof(int) != networkStream.Read(lengthBuffer, 0, 3))
return;
int length = BitConverter.ToInt32(lengthBuffer, 0);
int recv = 0;
using (FileStream stream = File.Create(nameOfTheFile + "." + extension))
{
byte #byte = 0x00;
while( (#byte = (byte)networkStream.ReadByte() ) != 0x00)
{
stream.WriteByte(#byte);
recv++;
}
stream.Flush();
}
On the sender part you can read the file extension then open up the file stream get the length of the stream then send the stream length to the client and "redirect" each byte from FileStream into a networkStream. This can look something like :
FileInfo meFile = //.. get the file
byte[] extBytes = Encoding.ASCII.GetBytes(meFile.Extension);
using(FileStream stream = meFile.OpenRead())
{
networkStream.Write(extBytes, 0, extBytes.Length);
networkStream.Write(BitConverter.GetBytes(stream.BaseStream.Length));
byte #byte = 0x00;
while ( stream.Position < stream.BaseStream.Length )
{
networkStream.WriteByte((byte)stream.ReadByte());
}
}
This approach is fairly easy to implement and doesn't require big changes if you want to send different file types. It lack some validator but I think you do not require this functionality.

Getting corrupted jpg files using TCP socket

i'm working with C#, i am connected to a server using one Async TCP socket, the purpose is that the server sends me 5 image files every second.
I took one tutorial about how to make the socket connection, so i think the problem is on the ReadCallBack function. Some jpgs arrive fine but other in a format that windows can't open and i can't understand why.
EDIT: After read different posts and look for more information, i changed completely the way to make that and finally is working fine, if somebody is in the same case, here is how i did it:
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
int cont = 0;
//i'm not sure why i was receiving a "\" character cathing file name, but this will control that
while (state.buffer[cont] != 0x0a && cont < StateObject.BufferSize)
cont++;
string inc_file_name = System.Text.Encoding.ASCII.GetString(state.buffer, 0, cont);
FileStream Fs = new FileStream(inc_file_name, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
int read_cont;
byte [] read_buffer = new byte [1024];
//till end of incoming file
while ((read_cont = handler.Receive(read_buffer)) > 0)
Fs.Write(read_buffer, 0, read_cont);
//save file
Fs.Close();
I hope it helps you.
Thanks for the comments and for your help.

using python to send an image over TCP to c# server

I am working on a project that uses a python script to send an image taken with a webcam to a c# webserver using sockets. I am currently sending strings to the server from the python client using code like:
info = bytearray("Text to send", "UTF-8")
socket.send(info)
to send data to the c# server and it functions perfectly for text and numbers. I run into an issue when trying to encode the data read from the .bmp into "UTF-8", as trying this returns an error of not being able to encode certain characters into UTF-8.
I was wondering if anyone had any idea of a way to encode this that c# will be able to recognize, or, if there is a better way of trying to implement this process, I am all ears.
A couple of options I have come up with would be to 1 - use something like google drive to save the image to, or an FTP server and then have the c# server retrieve it from there or 2 - create a packet system containing the RGB values and recreating the image from those pixel values on the server.
Thanks for your help.
EDIT: I have tried sending the file this way
data = bytearray("123456789","UTF-8")
file = open("image.bmp", "rb")
data += file.read()
socket.send(data)
and was able to successfully retreive the string "123456789", but the data after this is garbage. I have also implemented sending the size of the file before sending the data and that size number is retrieved fine, but the img data saves as a black bmp.
Edit 2 :
Here is the server and client code I am using to try and recreate the image using a memory stream. I the client code is using the process mentioned by hcalves.
Client
if __name__ == "__main__":
sock = socket.socket()
sock.connect(("localhost", 50839))
with open("image.bmp", "rb") as fd:
buf = fd.read(1024)
while (buf):
sock.send(buf)
buf = fd.read(1024)
sock.close()
Server
Socket client = server.AcceptSocket();
NetworkStream stream = new NetworkStream(client);
byte[] imgData = new byte[1024];
MemoryStream memstream = new MemoryStream();
stream.Read(imgData,0, 1024);
int counter = 0;
while (stream.DataAvailable)
{
memstream.Write(imgData, 0, 1024);
stream.Read(imgData, 0, 1024);
counter = counter + 1024;
}
memstream.Seek(0, SeekOrigin.Begin);
using (Stream file = File.OpenWrite("img.bmp"))
{
byte[] buffer = new byte[8*1024];
int len;
while ((len = memstream.Read(buffer, 0, buffer.Length)) > 0)
{
file.Write(buffer,0,len);
}
}
You shouldn't need more than this recipe:
import socket
if __name__ == "__main__":
sock = socket.socket()
sock.connect(("localhost", 50839))
with open("data.bin", "rb") as fd:
buf = fd.read(1024)
while (buf):
sock.send(buf)
buf = fd.read(1024)
sock.close()
For practical reasons, you can treat str objects (the result of fd.read) as raw data, you don't need any further crazy encoding. Just iterate the file and send over the socket. Test by running this server which just echoes to stdout with python server.py > data2.bin:
import socket
import sys
if __name__ == "__main__":
sock = socket.socket()
sock.bind(("localhost", 50839))
sock.listen(1)
client, address = sock.accept()
buf = client.recv(1024)
while (buf):
sys.stdout.write(buf)
buf = client.recv(1024)
client.close()
sock.close()
A checksum shows the binary data is sent correctly:
% md5 data.bin data2.bin
MD5 (data.bin) = 8b3280072275badf3e53a6f7aae0b8be
MD5 (data2.bin) = 8b3280072275badf3e53a6f7aae0b8be
Your C# server should be able to accept this data as is. If it doesn't work, it's because your server is expecting something in particular, not just raw data.

Categories

Resources