c# Form freez after try to socket connect - c#

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.

Related

C# Xamarin Recieve and Display image from Stream Byte Array with TCP Sockets

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

List of clients connected to Udp Server in C#

I have a socket program that works with Udp.
I want to manage clients that connect to the server.
For example, if the clients is connected to the server, add that client to a list.
I have already done this in Tcp with the following code:
static readonly Dictionary <int, TcpClient> list_clients = new Dictionary <int, TcpClient>();
For example, just the client who is on the list, his messages will be written.
I compared each clients with GetStream(). But in Udp I do not know how to do it. Can I manage clients ?
EDIT
I use the following code to receive a message from the client :
private static UdpClient udpServer = new UdpClient(11000);
private static IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 11000);
static void Main(string[] args)
{
var firstData = udpServer.Receive(ref remoteEP);
Console.WriteLine(Encoding.ASCII.GetString(firtsData);
}
Thanks in advance
this code works well for me!
Server:
public partial class Server : Form
{
public Server()
{
InitializeComponent();
}
void Print(string message)
{
listBox1.Items.Add(message);
}
private void button1_Click(object sender, EventArgs e)
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.Bind(new IPEndPoint(IPAddress.Loopback, 55555));
byte[] vs = new byte[100];
EndPoint senderRemote = new IPEndPoint(IPAddress.Any, 0);
Dictionary<EndPoint, int> pairs = new Dictionary<EndPoint, int>();
int id = 0;
for (int ii = 0; ii < 5; ii++)
{
socket.ReceiveFrom(vs, ref senderRemote);
if (pairs.ContainsKey(senderRemote))
Print(pairs[senderRemote].ToString() + " says:");
else
{
pairs.Add(senderRemote, id++);
Print("new sender");
}
Print(senderRemote.ToString());
Print(Encoding.Unicode.GetString(vs));
socket.SendTo(vs, senderRemote);
}
}
}
client:
public partial class Client : Form
{
public Client()
{
InitializeComponent();
}
Socket socket;
private void button1_Click(object sender, EventArgs e)
{
socket.Send(Encoding.Unicode.GetBytes("Gholamam!"));
byte[] vs = new byte[100];
socket.Receive(vs);
listBox1.Items.Add(Encoding.Unicode.GetString(vs));
}
private void Client_Load(object sender, EventArgs e)
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.Bind(new IPEndPoint(IPAddress.Loopback, new Random().Next(1024,65000)));
socket.Connect(IPAddress.Loopback, 55555);
}
}
don't forget that client and server are communicating. therefore they must use compromised way to communicate. if you like to store client information, it must be constant. for this, you must bind it to a fixed localEndPoint.
you can also use the solution in the question comments: you can add an id in messages. also you can use both.
P.S.: I'm using Socket Class instead of TCPClient or UDPClient because i found them awkward and inconsistent in some manners.

my server / client project not working

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.

Multiple socket connections using asynchronous sockets

I have the following code that makes a TCP socket connection to multiple end points as such:
private async void button1_Click(object sender, EventArgs e)
{
var listofIps = new List<string> { "192.168.168.193", "192.168.168.221" };
foreach (var ip in listofIps)
{
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(ip), 4001);
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
sockets.Add(client);
await client.ConnectTaskAsync(remoteEP);
await ReadAsync(client);
}
}
async Task ReadAsync(Socket s)
{
var args = new SocketAsyncEventArgs();
args.SetBuffer(new byte[1024], 0, 1024);
var awaitable = new SocketAwaitable(args);
while (true)
{
await s.ReceiveAsync(awaitable);
int bytesRead = args.BytesTransferred;
if (bytesRead <= 0) break;
var data = new ArraySegment<byte>(args.Buffer, 0, bytesRead);
AppendLog("RX: " + data.DumpHex());
}
}
public static string DumpHex(this ArraySegment<byte> data)
{
return string.Join(" ", data.Select(b => b.ToString("X2")));
}
public static Task ConnectTaskAsync(this Socket socket, EndPoint endpoint)
{
return Task.Factory.FromAsync(socket.BeginConnect, socket.EndConnect, endpoint, null);
}
However, the loop doesn't iterate pass the first IP address, because of the await ReadAsync.
Qn 1) How do I modify this code such that it iterates through my whole list of IPs without "awaiting" for the data be received completely. Do I remove the await keyword from await ReadAsync(client)?
Qn 2) How do I modify this code such that it connects to all the IPs at once. (is this possible?)
How do I modify this code such that it iterates through my whole list of IPs
Your code will iterate the whole list. But it will get to the second address only after it receives all data from the first address.
How do I modify this code such that it connects to all the IPs at once.
If you encapsulate the code for a single address into a separate async method, you can then first call it for each address and then await all the returned Tasks. Or you could use LINQ:
private async void button1_Click(object sender, EventArgs e)
{
var listOfIps = new List<string> { "192.168.168.193", "192.168.168.221" };
await Task.WhenAll(listOfIps.Select(ip => ReadFromAddress(ip)));
}
private async Task ReadFromAddress(string address)
{
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(ip), 4001);
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
sockets.Add(client);
await client.ConnectTaskAsync(remoteEP);
await ReadAsync(client);
}

Send video frame via socket

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.

Categories