I captured video stream with Kinect device. I need to Send this streams over network. For this purpose I used sockets.
Her is piece of code in server and client:
private System.Drawing.Bitmap _CurrentBitmap;
public ManWindow()
{
InitializeComponent();
this.Loaded += delegate
{
BackgroundWorker bw1 = new BackgroundWorker();
bw1.RunWorkerCompleted += (a, b) => bw1.RunWorkerAsync();
bw1.DoWork += delegate { SendImage(); };
bw1.RunWorkerAsync();
};
}
public void SendImage()
{
Socket sListen = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
IPAddress IP = IPAddress.Parse("127.0.0.1");
IPEndPoint IPE = new IPEndPoint(IP, 4321);
sListen.Bind(IPE);
sListen.Listen(2);
while (true)
{
Socket clientSocket;
clientSocket = sListen.Accept();
var converter = new System.Drawing.ImageConverter();
byte[] buffer = (byte[])converter.ConvertTo(_CurrentBitmap, typeof(byte[]));
clientSocket.Send(buffer, buffer.Length, SocketFlags.None);
}
}
Client:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
BackgroundWorker bw11111 = new BackgroundWorker();
bw11111.RunWorkerCompleted += (a, b) => bw11111.RunWorkerAsync();
bw11111.DoWork += delegate { Recive(); };
bw11111.RunWorkerAsync();
Recive();
}
public void Recive()
{
Socket s = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
IPAddress IP = IPAddress.Parse("127.0.0.1");
IPEndPoint IPE = new IPEndPoint(IP, 4321);
s.Connect(IPE);
while (true)
{
byte[] buffer = new byte[1000000];
s.Receive(buffer, buffer.Length, SocketFlags.None);
MemoryStream ms = new MemoryStream(buffer);
ms.Write(buffer, 0, buffer.Length);
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(ms);
Dispatcher.BeginInvoke(new Action(() =>
{
rgbImage11.Source = bitmap.ToBitmapSource();
}));
}
}
_CurrentBitmap is frame that readed from Kinect and every 1 second updated. When Client starts, call Socket Receive method, it receives frame and after convert to bitmap asign it to Image WPF control. My problem is this action occurs ones and loop in client not repeated.
I think you are doing it right, although depending on your needs UDP sockets might make more sense.
Try changing your Server code to something like this:
while (true)
{
Socket clientSocket;
clientSocket = sListen.Accept();
var converter = new System.Drawing.ImageConverter();
while(true) // find a better way to determine that the picture is still updating?
{
byte[] buffer = (byte[])converter.ConvertTo(_CurrentBitmap, typeof(byte[]));
clientSocket.Send(buffer, buffer.Length, SocketFlags.None);
}
}
You were sending one bitmap to your client, then falling out of the loop.
The socket will not stay open, so your client runs it's loop once.
Related
I am currently working on a project that I send an Image through TCP using sockets from a WinForm Application to a Xamarin Android App in the same network.
I've tested the Server ( WinForms ) code using a client ( also Winforms) and managed it to work. But the problem comes, when I code for Android client in Xamarin I find out that I cannot use Bitmap the same way, so I tried to find other ways.
The problem is with the android Client code. I've checked in debugging that the image bytes get all through from Server -> Client.
On the Android Client :
If I remove the while loop and start playing with the Send button ( server) and Connect Button(Client) some images show up on the clients side. That's odd
I am not an expert on these matters so feel free to suggest any corrections
The codes that I use
The Code in my WinForms Server is this.
private void StartServer_Click(object sender, EventArgs e)
{
IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.1.2"), 9999);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(iep);
server.Listen(100);
Console.WriteLine("Waiting for client....");
client = server.Accept();
}
private void SendImage_Click(object sender, EventArgs e)
{
Bitmap bmp = TakingScreenshotEx1(); // method for taking screenshot
bmp.Save("1.jpeg", ImageFormat.Jpeg); // the name of the screenshot taken, just before
byte[] buffer = ReadImageFile("1.jpeg"); // read the saved image file
int v = client.Send(buffer, buffer.Length, SocketFlags.None); // send the image
Console.WriteLine("Image SENT!");
}
My WinForms Client ( newbie but working method )
IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.1.2"), 9999);
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
byte[] buffer = new byte[1000000];
private async void Connect_Click(object sender, EventArgs e)
{
if(client.Connected != true)
client.Connect(iep);
await Task.Run(() => DoSomethingLong());
}
private async void DoSomethingLong()
{
while (true)
{
int v = client.Receive(buffer, buffer.Length, SocketFlags.None);
Console.WriteLine("Data Received!");
Stream stream = new MemoryStream(buffer);
var img = Bitmap.FromStream(stream);
pictureBox1.Image = img;
}
}
The problematic Android Client
IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.1.2"), 9999);
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
byte[] buffer = new byte[1000000];
private async void Connect_Clicked(object sender, EventArgs e)
{
if (client.Connected != true)
client.Connect(iep);
await Task.Run(() => DoSomethingLong());
}
public Xamarin.Forms.ImageSource PhotoStream { get; set; }
private async void DoSomethingLong()
{
while(true){
int v = client.Receive(buffer, buffer.Length, SocketFlags.None);
Console.WriteLine("Data Received!");
Stream stream = new MemoryStream(buffer);
if (stream != null)
imgXam.Source = ImageSource.FromStream(() => stream);
}
}
SOLVED
Following #Jason's advice and putting the Invoke Method inside a Timer . I was able to solve the problem
Device.StartTimer(TimeSpan.FromMilliseconds(500), () =>
{
// called every 1 second
MainThread.BeginInvokeOnMainThread(() =>
{
});
return true; // return true to repeat counting, false to stop timer
});
When I use "127.0.0.1" on the same computer, it works just fine. If I try to use the server's public ip address, it doesn't work (actually I get a socket error). If I make it ipaddress.any it doesn't give an error, but it doesn't work, either. I thought maybe it's because I'm on the same computer, so I put the server on my desktop and client on my laptop, and I connected my laptop to my phone's hotspot so the ipaddress is different. It still doesn't work. The message gets sent, but never received. What am I doing wrong?
struct DataPacket
{
public IPEndPoint destination;
public byte[] data;
public DataPacket(IPEndPoint destination, byte[] data)
{
this.destination = destination;
this.data = data;
}
}
AsyncPriorityQueue<DataPacket> queuedReceiveData = new AsyncPriorityQueue<DataPacket>(NetworkConstants.MAX_PLAYERS_PER_SERVER, false);
Socket sck;
IPEndPoint ipEndPoint;
bool listening = true;
bool processing = true;
void Start()
{
sck = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
#if SERVER
ipEndPoint = new IPEndPoint(IPAddress.Any, NetworkConstants.SERVER_PORT);
sck.Bind(ipEndPoint);
#else
ipEndPoint = new IPEndPoint(IPAddress.Parse(NetworkConstants.SERVER_IP), NetworkConstants.SERVER_PORT);
EndPoint ep = new IPEndPoint(IPAddress.Any, 0); // doesn't work at all
//EndPoint ep = new IPEndPoint(IPAddress.Parse(NetworkConstants.SERVER_IP), 0); // says requested address is not valid in its context
//EndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 0); // works only on same computer
sck.Bind(ep);
#endif
new Thread(() => ListenForData()).Start();
new Thread(() => ProcessData()).Start();
#if !SERVER
SerializeCompact.BitStream bs = new SerializeCompact.BitStream();
bs.Write(Headers.Connect, minHeader, maxHeader);
SendData(bs.GetByteArray());
#endif
}
void OnDestroy()
{
listening = false;
processing = false;
sck.Close();
}
public void SendData(byte[] data)
{
var packet = queuedSendData.Dequeue();
sck.SendTo(data, 0, data.Length, SocketFlags.None, ipEndPoint);
print("message sent to server");
}
public void SendDataTo(byte[] data, IPEndPoint endPoint)
{
var packet = queuedSendData.Dequeue();
sck.SendTo(data, 0, data.Length, SocketFlags.None, endPoint);
print("message sent to client");
}
void ListenForData()
{
while (listening)
{
EndPoint endPoint = ipEndPoint;
byte[] buffer = new byte[1024];
int rec = sck.ReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref endPoint);
Array.Resize(ref buffer, rec);
queuedReceiveData.Enqueue(new DataPacket((IPEndPoint) endPoint, buffer), 0);
print("received message");
ProcessData(buffer);
}
}
void ProcessData()
{
while (processing)
{
var rcv = queuedReceiveData.Dequeue(); // blocks until an item can be dequeued
byte[] data = rcv.data;
IPEndPoint ep = rcv.destination;
// process data...
}
}
I have some weird problem with two c# server sockets.
I have 2 servers. One is asynchronous and second is synchronous. I have also client in android which sends picture to this servers.
Synchronous Server:
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public void Start()
{
byte[] bytes = new Byte[1024000];
String content = String.Empty;
IPAddress ipAddress = IPAddress.Parse("192.168.1.2");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 53100);
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
while (true)
{
//// Program is suspended while waiting for an incoming connection.
Socket handler = listener.Accept();
data = null;
// An incoming connection needs to be processed.
while (true)
{
bytes = new byte[1024000];
int bytesRec = handler.Receive(bytes);
strBuilder.Append(Encoding.ASCII.GetString(bytes, 0, bytesRec));
if (strBuilder.Length > 1)
{
content = strBuilder.ToString();
byte[] xdata = Convert.FromBase64String(content);
using (var mStream = new MemoryStream(xdata, 0, xdata.Length))
{
pictureBox1.Image = Image.FromStream(mStream, true);
}
}
}
byte[] msg = Encoding.ASCII.GetBytes(data);
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void Form1_Load(object sender, EventArgs e)
{
thr = new Thread(new ThreadStart(Start));
thr.Start();
}
Asynchronous Server:
public void StartListening()
{
listener.Bind(new IPEndPoint(IPAddress.Parse("192.168.1.2"), 53100));
listener.Listen(1);
allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
public void AcceptCallback(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject stateObj = new StateObject();
stateObj.clientSocket = handler;
handler.BeginReceive(stateObj.buffer, 0, StateObject.buffSize, 0,
new AsyncCallback(ReadCallback), stateObj);
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
public void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
StateObject stateObj = (StateObject)ar.AsyncState;
Socket handler = stateObj.clientSocket;
SocketError errorCode;
int bytesRead = handler.EndReceive(ar, out errorCode);
if (errorCode != SocketError.Success)
{
bytesRead = 0;
}
if (bytesRead > 0)
{
stateObj.strBuilder.Append(Encoding.ASCII.GetString(stateObj.buffer, 0, bytesRead));
handler.BeginReceive(stateObj.buffer, 0, stateObj.buffer.Length, SocketFlags.None, new AsyncCallback(ReadCallback), stateObj);
}
else
{
if (stateObj.strBuilder.Length > 1)
{
content = stateObj.strBuilder.ToString();
Debug.WriteLine(content);
byte[] data = Convert.FromBase64String(content);
using (var mStream = new MemoryStream(data, 0, data.Length))
{
pictureBox1.Image = Image.FromStream(mStream, true);
}
recImage = (Bitmap)pictureBox1.Image;
imgImage = new Image<Bgr, Byte>(recImage);
imageBox1.Image = imgImage;
while (imageBox1.Image != null)
{
SURFDetectionAndGUIUpdate(this, new EventArgs());
}
string xname = name.ToString();
Send(handler, xname);
}
}
}
private void Send(Socket handler, String data)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
private void SendCallback(IAsyncResult ar)
{
try
{
Socket handler = (Socket)ar.AsyncState;
int bytesSent = handler.EndSend(ar);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The problem is that when I send picture from client to synchronous server everything works and server receives it, but if I send picture from the same client to asynchronous server it doesn't receive it.
Currently your synchronous server attempts to create a bitmap from the data of the first Receive, and the asynchronous server waits until the client disconnects before trying to create a bitmap from the data.
TCP streams data, which means that you can read data as it arrives, in the order it was sent, but sending 1000 bytes doesn't mean you'll receive 1000 bytes at once. You could even receive data from two different message in a single Receive operation. The more data you send, and the more times you send data, the bigger the chance that this effect will occur.
In the comments you mention that the client is going to send multiple images, so before you continue you should decide how you want to determine when the first image is received and when data for the second image starts:
You could choose to let the client disconnect after sending each image, as the asynchronous server currently expects
You could choose to first send the number of bytes of an image, before sending the image data itself. Make sure the size itself is encoded at a fixed length. This prevents you from having to reconnect all the time, and also allows you to predetermine the size of the receive buffers
Or you could delimit the data using a byte outside the base64 range, but this requires scanning through the received data
i created form appliction, and tried to make chat with socket i have problem when its execute line "acc = sck.Accept();" the form freez and cant press any button whats is in Form, basicly, freez! What im foing wrong? Doing by tutorial
static Socket sck;
static Socket acc;
static int port = 9000;
static IPAddress ip;
static Thread rec;
private void button2_Click(object sender, EventArgs e){
rec = new Thread(recV);
ip = IPAddress.Parse(GetIp());
sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sck.Bind(new IPEndPoint(ip, port));
sck.Listen(0);
acc = sck.Accept();
/*while (true)
{
byte[] sdata = Encoding.ASCII.GetBytes("TEST");
acc.Send(sdata, 0, sdata.Length, 0);
}*/
}
Use AcceptAsync like this:
private async void button2_Click(object sender, EventArgs e){
rec = new Thread(recV);
ip = IPAddress.Parse(GetIp());
sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sck.Bind(new IPEndPoint(ip, port));
sck.Listen(0);
acc = await sck.AcceptAsync();
//This will block here, let the UI thread continue and then resume when a connection is accepted
/*while (true)
{
byte[] sdata = Encoding.ASCII.GetBytes("TEST");
acc.Send(sdata, 0, sdata.Length, 0);
}*/
}
Note that the method is now async and I'm using await in front of theAcceptAsync` call.
If you want your Send/Receive methods to also free the UI, look into their corresponding Async method.
I have a server project with socket and a client project with socket in c#, that, when I start my server project, my form is not working, like is lock.
please help me...
What do I do for resolving that my form works and textbox shows messages?
private void button1_Click(object sender, EventArgs e)
{
try
{
port = 11000;
ip = IPAddress.Any;
IPEndPoint ipLocal = new IPEndPoint(ip, port);
socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socketServer.Bind(ipLocal);
socketServer.Listen(10);
buffersize = 1024;//از این سایزه همه چی از گووره این در می آد
newClient = socketServer.Accept();
while (true)
{
buffer = new byte[buffersize];
recv = newClient.Receive(buffer, 0, buffer.Length, SocketFlags.None);
if (recv != 0)
{
message = Encoding.ASCII.GetString(buffer, 0, recv);
textBox1.Text += message;
//socketServer.Close();
//newClient.Close();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
in client:
private void button1_Click(object sender, EventArgs e)
{
try
{
bufferSize = 1024;
ip = IPAddress.Parse("192.168.1.10");
port = 11000;
socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipEnd = new IPEndPoint(ip, port);
socketClient.Connect(ipEnd);
while (true)
{
buffer = new byte[bufferSize];
message = textBox1.Text;
buffer = Encoding.ASCII.GetBytes(message);
snd = socketClient.Send(buffer, 0, buffer.Length, SocketFlags.None);
//socketClient.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
In your Server :
You problem is due to blocking nature of Socket.Recieve() read .
It says :
If no data is available for reading, the Receive method will block until data is available
And you run this in same UI thread, so you feel your UI to be freeze.
Solution : Transfer your socket function to another thread. And to update text box, use Invokes.
Also in your implementation both Server and Client, you run a while loop infinitely. Since they are running in UI thread, you will feel the freeze.
Your applications locks up because you have an infinite loop in you click event handlers. You will have to start a Thread to do the read and write operations as not to block your main visualization thread.