Using UdpClient, how do you retry UdpClient.Connect() until it succeeds? - c#

My client/server programs work well with each other, but only when the server is up and running before my client starts. If the client fails to connect on the first try, I can't get it to try again.
Here's my Client's connect method.
public void connect()
{
IPAddress server_address = IPAddress.Parse("127.0.0.1");
IPEndPoint server_ip = new IPEndPoint(server_address, 5685);
Console.WriteLine("2");
bool connected = false;
while (!connected)
{
try
{
Console.WriteLine("IN CONNECTED");
udp_client.Connect(server_ip);
byte[] send_data = Encoding.ASCII.GetBytes("INIT");
udp_client.Send(send_data, send_data.Length);
byte[] received_bytes = udp_client.Receive(ref server_ip);
string received_data = Encoding.ASCII.GetString(received_bytes);
if (received_data == "INIT")
{
connected = true;
Console.WriteLine("RECEIVED INIT");
listen(server_ip);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
What I was hoping to see is the udp_client.Connect(server_ip) to loop until I received that "INIT" message from the server.
As it currently stands, there is no loop. It seems to get stuck on udp_client.Receive(ref server_ip).
Any help would be appreciated!

This is pseudoCode - you will have to move somethings to class scope to allow future send/receives (which you'd do using a different method). This is only designed to show you how to connect when the connection blocks:
bool isClientConnected = false;
var connector = new System.ComponentModel.BackgroundWorker();
public void connectToUDP(){
connector.DoWork+= connect;
connector.RunWorkerAsync();
}
private void connect(object sender, DoWorkEventArgs e)
{
IPAddress server_address = IPAddress.Parse("127.0.0.1");
IPEndPoint server_ip = new IPEndPoint(server_address, 5685);
Console.WriteLine("2");
try
{
Console.WriteLine("Waiting for server...");
udp_client.Connect(server_ip);
byte[] send_data = Encoding.ASCII.GetBytes("INIT");
udp_client.Send(send_data, send_data.Length);
byte[] received_bytes = udp_client.Receive(ref server_ip);
string received_data = Encoding.ASCII.GetString(received_bytes);
if (received_data == "INIT")
{
isClietConnected = true;
Console.WriteLine("now connected");
listen(server_ip);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
public bool sendReceiveUDP(string send){
if(!isClientConnected){
return false;
}
//perform send
return true;
}
You would then maintain the connected session using class scope and send/receive using a different method. This is for connect only since you only need to do it once.
How you set something like this up:
private bool isConnected = false();
private bool send(){
if(!isConnected){
connect();
}
//send
}
private bool connect(){
if(!isConnected){
//launch connection thread
}
}
private delegate void onNewReceive(string message);
public event onNewReceive onNewReceiveEvent;
public void fireEvent(string message){
onNewReceiveEvent.Invoke(message);
}
private void waitForData(object sender, DoWorkEventArgs e){
//this is the backgroundworker
while(true){
receive();
fireEvent(message);
}
}
Then, subscribe to the onNewREceivedEvent in another class and process the inbound message. onNewReceivedEvent += processInboundMEsasage();
This is all psuedocode and "brain compiled" (creit to others) so it's only meant for demonstrations. Without intellisense, I'm lost.

Related

system.net.sockets.socketexception the remote server closed connection

I have this code on my server side.
public static void Data_IN(object cSocket)
{
Socket clientSocket = (Socket)cSocket;
byte[] Buffer;
int readBytes;
while (true)
{
Buffer = new byte[clientSocket.SendBufferSize];
readBytes = clientSocket.Receive(Buffer);
if (readBytes > 0)
{
Packet p = new Packet(Buffer);
DataManager(p);
}
}
}
And the main problem is that when I stop debugging the code the server always crashes and says
System.Net.Sockets.SocketException: the remote server closed connection
The error is always at readBytes = clientSocket.Recieve(Buffer);
That is the only way I can crash the server, my only concern is when someone uses the chat program that I have created and his/hers computer crashes the chat server will go down and I always need to restart the server.
Clientside code below which executes when closing the window
private void MainWindow_Closed(object sender, EventArgs e)
{
if (isConnected)
{
Packet p = new Packet(PacketType.CloseConnection, ID);
p.data.Add(login);
p.data.Add("exits from chat");
socket.Send(p.ToBytes());
socket.Close();
isConnected = false;
thread.Abort();
}
}
On below there is the code part which uses data_in, that code is on the client side
private void ConnectBtn_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(Login.Text))
{
MessageBox.Show("Add username");
}
else if (!IPAddress.TryParse(serverIP.Text, out ipAdress))
{
MessageBox.Show("Add valid ip");
}
else
{
ClearRequireMsg();
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipEndPoint = new IPEndPoint(ipAdress, 4242);
try
{
socket.Connect(ipEndPoint);
login = Login.Text;
isConnected = true;
ConnectBtn.IsEnabled = false;
SendBtn.IsEnabled = true;
thread = new Thread(Data_IN);
thread.Start();
}
catch (SocketException ex)
{
AddMsgToBoard("Error during connecting to server", "System");
}
}
}
You're calling the function Data_IN without passing any parameter.
thread = new Thread(Data_IN);
Right way:
new Thread(() => Data_IN(socket));

TCPIP connection in c# and data sending/receiving in another threads

I have a problem with my TCPIP connection Form programm.
I have a code, where I'm trying to send and receive some data from server.
The main problem of my app is how to reconcile some threads:
myListenThread - to listening data from server
myReadStreamThread - to read data from server
System.Threading.Thread - main thread eg. to write data to server
captureThread - to do another things like capturing images from camera
Part of my code:
private void buttonConnect_Click(object sender, EventArgs e)
{
try
{
Connect();
Connected = true;
this.myListenThread = new Thread(new ThreadStart(Listen));
this.myListenThread.Start();
}
catch
{
MessageBox.Show("Invalid host! Try again.");
}
}
private void Listen()
{
this.myReadStreamThread = new Thread(new ThreadStart(ReadStream));
this.myReadStreamThread.Start();
while (Connected)
{
if (!myReadClient.Connected)
{
Connect();
}
}
}
private void Connect()
{
IPAddress IP = IPAddress.Parse(textboxIP.Text);
int PORT = Convert.ToInt32(textboxPORT.Text);
this.myReadClient = new TcpClient();
this.myReadClient.Connect(IP, PORT);//SOMETIMES HERE'S AN ERROR
this.myStream = this.myReadClient.GetStream();
Properties.Settings.Default.IP = Convert.ToString(IP);
Properties.Settings.Default.PORT = Convert.ToString(PORT);
Properties.Settings.Default.Save();
}
private void ReadStream()
{
while (true)
{
try
{
this.myReadBuffer = new byte[this.myReadClient.ReceiveBufferSize];
this.myBufferSize = myStream.Read(myReadBuffer, 0, this.myReadClient.ReceiveBufferSize);
if (myBufferSize != 0)
{
this.myString = Encoding.ASCII.GetString(myReadBuffer);
//myDelegate myDel;
//myDel = new myDelegate(Print);
//richtextboxRead.Invoke(myDel);
}
}
catch
{
break;
}
}
}
All is working correct when I'm connecting to server, but when I want to send some string the problem appears because of threads.
I decided to send string, by clicking Button3 and waiting until I receive string "1" from server using while loop:
private void button3_Click(object sender, EventArgs e)
{
this.captureThread = new Thread(new ThreadStart(() => this.newGame()));
this.captureThread.Start();
}
private bool newGame()
{
string command = "12345abc";
if (Connected)
{
WriteStream(command);
}
while (myBufferSize == 0 && myString !="1") { }
Thread.Sleep(2000);
...//doing other things
}
private void WriteStream(string command)
{
Connect();
this.myWriteBuffer = Encoding.ASCII.GetBytes(command);
this.myStream.Write(this.myWriteBuffer, 0, command.Length);
}
And the problem with connection and data send/receive problem appears, when it should write my string "command" - it doesn't react. MyBufferSize is always 0 and myString is always null. Sometimes an Error about connection appears when I click Button3 (assigned in code). I think it is because in captureThread I can't see any data from another threads. How to solve it?

How to change status of label when a sql server goes down

I have this block of code in my c# application:
private bool connected
public void ChangeStatusa()
{
if(connected)
{
label1.Text="Connected"
}else{
label1.Text="Connected"
}
}
I want to auto execute this code when the sql server is disconnected,
and I want to do this work in the background without affecting my application performance.
Essentially, I want to create a system in my application which is responsible for checking the sql server connectivity, and auto change the status when the connection is lost.
Are you connecting via tcp? if so you could try using a straight socket connection with an async receive : here's some code :
class Program
{
static bool disc = false;
static void Main(string[] args)
{
dbtest dt = new dbtest();
dt.Disconnected += new EventHandler(dt_Disconnected);
dt.Start("10.1.32.97", 1433);
while (!Console.KeyAvailable)
{
Console.WriteLine(disc?"disconnected":"tick");
Thread.Sleep(2000);
}
dt.Stop();
}
static void dt_Disconnected(object sender, EventArgs e)
{
disc = true;
Console.WriteLine("Disconnected");
}
}
public class dbtest
{
byte[] buffer = new byte[10];
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public event EventHandler Disconnected = null;
public void Start(string host, int port)
{
if(s!=null)
{
Stop();
}
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.Connect(host, port);
Console.WriteLine("Connected.");
s.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallBack, s);
}
public void Stop()
{
if (s != null)
{
s.Close();
s.Dispose();
s = null;
}
}
void ReceiveCallBack(IAsyncResult ar)
{
Socket s = ar as Socket;
if (s != null && s.Connected)
{
int rcvd = s.EndReceive(ar);
if (rcvd > 0)
{
s.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallBack, s);
return;
}
}
if(Disconnected!=null)
Disconnected(this, EventArgs.Empty);
}
}
This is just basic - I'm not sure how long sql server will keep hold of a socket that hasn;t responded. Maybe add a count - reconnect on disconnect to see if its actually a real disconnect etc etc ...
Sounds like a Timer would work for this purpose. Background thread in an infinite loop with a thread sleep would also work but I dont like anything in an infinite loop.
See
C# Background Thread
Here is a fxn to check your connection
namespace answer1
{
using System.ComponentModel;
using System.Data.SqlClient;
internal class ConnectionCheck
{
private BackgroundWorker bw = new BackgroundWorker();
private void CheckConnection()
{
string connetionString = null;
SqlConnection cnn;
connetionString = "Data Source=ServerName;Initial Catalog=DatabaseName;User ID=UserName;Password=Password";
cnn = new SqlConnection(connetionString);
try
{
cnn.Open();
Console.WriteLine("Connection Open ! ");
cnn.Close();
}
catch (Exception ex)
{
Console.WriteLine("Can not open connection ! ");
}
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
CheckConnection();
System.Threading.Thread.Sleep(5000);
}
}
/// <summary>
/// This is the Main routine you call to execute the background thread
/// </summary>
public void RunBackgroundSQLCheck()
{
bw.DoWork += this.bw_DoWork;
bw.RunWorkerAsync();
}
}
}

disconnect/close a client [duplicate]

This question already has an answer here:
C# -- TcpListener.Start() causing SocketException with message "Only one usage of each socket address"
(1 answer)
Closed 2 years ago.
I have a simple client-server application which works like this: the server is always listening (in a separate thread) for a client connection (which sends the name of process that it wants the server to kill).
Here is the server:
private void btnStart_Click(object sender, EventArgs e)
{
_port = int.Parse(comboBoxPorts.SelectedItem.ToString());
_tcpListener = new TcpListener(_ipAddress, _port);
_keepRunning = true;
_listenerThread = new Thread(Listen);
HandleListenerThreadStartListenEvent += HandleListenerThreadStartedEventMethod;
ListenerThreadStartedEvent += HandleListenerThreadStartListenEvent;
_listenerThread.Start();
}
private void btnStop_Click(object sender, EventArgs e)
{
if (_tcpListener != null)
{
_keepRunning = false;
if (_tcpListener.Server.Connected)
{
_tcpListener.Server.Disconnect(true);
}
_tcpListener.Stop();
}
labelServerStatus.Text = "Server is stopped";
comboBoxPorts.Enabled = true;
btnStart.Enabled = true;
btnStop.Enabled = false;
}
private void Listen()
{
try
{
_tcpListener.Start();
OnListenerThreadStartListenEvent(); // just update the GUI
}
catch(Exception e)
{
MessageBox.Show("Port " + _port + " is NOT available." + Environment.NewLine +
"Please choose another one: " + e.Message);
return;
}
_keepRunning = true;
string ballonMessage = "Socket Server Running at " + _ipAddress + ", port: " + _port;
notifyIcon1.ShowBalloonTip(2000, "Simplex Listener", ballonMessage, ToolTipIcon.Info);
while (_keepRunning)
{
try
{
#region using AcceptSocket()
_clientSocket = _tcpListener.AcceptSocket();
string checkString = string.Empty;
IPAddress ipOfClient = ((IPEndPoint) _clientSocket.LocalEndPoint).Address;
notifyIcon1.ShowBalloonTip(2000, "Simplex Listener", "New client has connected from ip " + ipOfClient, ToolTipIcon.Info);
byte[] buffer = new byte[SIZE_OF_BUFFER];
int bytesReceived = _clientSocket.Receive(buffer);
// Concatenate chars as bytes to a received string.
for (int i = 0; i < bytesReceived; i++)
checkString += Convert.ToChar(buffer[i]);
//..... getting the name of process and kill it (and than open it...
RestartProcess(nameOfProcess, windowName, pathToExeFile);
// Client is waiting to know operation is complete- so send him some char...
ASCIIEncoding encoder = new ASCIIEncoding();
_clientSocket.Send(encoder.GetBytes("v"));
_clientSocket.Disconnect(true);
_clientSocket.Close();
#endregion
}
catch (Exception )
{
}
}
}
The client side:
public void RestartTheSoftwareInServerComputer(string ipOfServer, int portNumber)
{
TcpClient client = new TcpClient();
if (_serverEndPoint == null)
{
_serverEndPoint = new IPEndPoint(IPAddress.Parse(ipOfServer), portNumber);
}
client.Connect(_serverEndPoint);
// Send the command to the server:
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("....detailsOfProcess....");
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
// Now, wait for the server's response [which means the process had been restart].
NetworkStream stream = client.GetStream();
byte[] bytes = new byte[5];
stream.Read(bytes, 0, 5);
string response = Encoding.UTF8.GetString(bytes, 0, 1);
if (response.Equals("x"))
{
throw new Exception("Failed to restart X software.");
}
stream.Close();
client.Close();
}
When I stop and restart the server (when no client had connected), then everything is OK.
The problem is when the server got some client connected, and is restarted, then the client has disconnected and the server needs to be restarted. When we hit the "START SERVER" again it will get the exception:
Only one usage of each socket address (protocol/network address/port)
is normally permitted.
How should I close the port?
When you exit your server, you should call _tcpListener.Stop() to close the main socket that the server is listening on.
Edit: You could also try to call _listenerThread.Join() in your stop button click, to wait for the listener thread to finish, before starting the next one.
private void btnStop_Click(object sender, EventArgs e)
{
if (_tcpListener != null)
{
_keepRunning = false;
if (_tcpListener.Server.Connected)
{
_tcpListener.Server.Disconnect(true);
_tcpListener.Stop();
if (_clientSocket != null)
{
_clientSocket.Close();
_clientSocket = null;
}
_listenerThread.Join();
}
}
labelServerStatus.Text = "Server is stopped";
comboBoxPorts.Enabled = true;
btnStart.Enabled = true;
btnStop.Enabled = false;
}
EDIT 2:
here is a windows form that does similar to your server. I didn't need a client, just use "telnet localhost 49152" from a command prompt to 'pretend' to be the client connecting.
public partial class Form1 : Form
{
private TcpListener _tcpListener;
private bool _keepRunning;
private Thread _listenerThread;
private Socket _clientSocket;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var address = IPAddress.Parse("127.0.0.1");
_tcpListener = new TcpListener(address, 49152);
_keepRunning = true;
_listenerThread = new Thread(Listen);
_listenerThread.Start();
button1.Enabled = false;
button2.Enabled = true;
}
private void Listen()
{
try
{
_tcpListener.Start();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
return;
}
_keepRunning = true;
while (_keepRunning)
{
try
{
_clientSocket = _tcpListener.AcceptSocket();
var buffer = new byte[8192];
var bytesReceived = _clientSocket.Receive(buffer);
var checkString = String.Empty;
if (_keepRunning)
{
// bytesReceived can be 0 if the remote socket disconnected
if (bytesReceived > 0)
{
checkString = Encoding.ASCII.GetString(buffer, 0, bytesReceived);
// Client is waiting to know operation is complete- so send him some char...
var encoder = new ASCIIEncoding();
_clientSocket.Send(encoder.GetBytes("v"));
}
if (_clientSocket.Connected) _clientSocket.Disconnect(true);
}
_clientSocket.Close();
}
catch (Exception ex)
{
// really should do something with these exceptions
}
}
}
private void button2_Click(object sender, EventArgs e)
{
if (_tcpListener != null)
{
_keepRunning = false;
if (_tcpListener.Server.Connected)
{
_tcpListener.Server.Disconnect(true);
}
_tcpListener.Stop();
if (_clientSocket != null)
{
_clientSocket.Close();
_clientSocket = null;
}
_listenerThread.Join();
}
button1.Enabled = true;
button2.Enabled = false;
}
}
There are a lot of problems with this code, e.g. sharing variables across threads etc. but on my machine the Join doesn't seem to block for any length of time. The problem with _keepRunning is that on certain systems it's possible for one thread to not see the change from true to false, because it gets optimised or cached. You should really use some form of thread synchronisation, make it volatile, or wrap it in a lock etc. I'd suggest you have a read here about this. I'd also suggest you have a read up on Sockets too, or if as other commenters have mentioned, if you aren't interested in learning about all the idiosyncrasies of sockets and threading, perhaps you should look for a higher level library that hides it all?

Need help with a C# Asynchronous Socket Program that has multiple sends

So, I have a board game that uses Asynchronous socket to operate over LAN. The thing is, I have little to no understanding of Asynchronous socket programming, or of threads, but I do my best to try.
I based my program off a chat program, so I use that part to send multiple strings.
So, here's part of the code for the Client:
private void Connect(IAsyncResult iar)
{
try
{
Socket client_conn = (Socket)iar.AsyncState;
client_conn.EndConnect(iar);
g_bmsg = new byte[1024];
check = true;
string szData = "#Player " + lblName.Text + " connected.";
sendingFunction(szData);
g_client_conn.BeginReceive(g_bmsg, 0, g_bmsg.Length, SocketFlags.None, new AsyncCallback(Receive), g_client_conn);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "GG");
}
}
private void Send(IAsyncResult iar)
{
Socket client_conn = (Socket)iar.AsyncState;
client_conn.EndSend(iar);
}
private void Receive(IAsyncResult iar)
{
if (g_bmsg.Length != 0)
{
SetLabelText(Encoding.ASCII.GetString(g_bmsg, 0, g_bmsg.Length));
check = false;
}
}
private void SetLabelText(string txt)
{
if (lblBuffer.InvokeRequired)
lblBuffer.Invoke(new MethodInvoker(delegate { SetLabelText(txt); }));
else
{
lblBuffer.Text = txt;
}
if (lblBuffer.Text.StartsWith("#"))
{
lblStatmsg.Text = lblBuffer.Text.Replace("#", "");
}
if (lblBuffer.Text.StartsWith("$"))
{
lblStatmsg.Text = "Server Settings Received.";
lblBuffer.Text = lblBuffer.Text.Replace("$", "");
option_Postn = int.Parse(lblBuffer.Text.Substring(0, 1));
option_First = int.Parse(lblBuffer.Text.Substring(2, 1));
}
if (lblBuffer.Text.StartsWith("#"))
{
MessageBox.Show(lblBuffer.Text);
}
}
And here's part of the code for the Server:
private void Accept(IAsyncResult iar)
{
Socket server_conn = (Socket)iar.AsyncState;
g_server_conn = server_conn.EndAccept(iar);
g_bmsg = new byte[1024];
check = true;
g_server_conn.BeginReceive(g_bmsg, 0, g_bmsg.Length, SocketFlags.None, new AsyncCallback(Recieve), g_server_conn);
}
private void Send(IAsyncResult iar)
{
Socket server_conn = (Socket)iar.AsyncState;
server_conn.EndSend(iar);
}
private void Recieve(IAsyncResult iar)
{
try
{
Socket server_conn = (Socket)iar.AsyncState;
server_conn.EndReceive(iar);
if (g_bmsg.Length != 0)
{
SetLabelText(Encoding.ASCII.GetString(g_bmsg, 0, g_bmsg.Length));
check = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "GG");
}
}
private void SetLabelText(string txt)
{
if (lblBuffer.InvokeRequired)
lblBuffer.Invoke(new MethodInvoker(delegate { SetLabelText(txt); }));
else
{
lblBuffer.Text = txt;
}
if (lblBuffer.Text.StartsWith("#"))
{
lblStatmsg.Text = lblBuffer.Text.Replace("#", "");
}
else if (lblBuffer.Text.StartsWith("#"))
{
MessageBox.Show(lblBuffer.Text);
}
else if (lblBuffer.Text.StartsWith("%"))
{
}
}
Basically, since the game sends more than messages (it can send settings, or game pieces, etc), I ran the sender function everytime I need to send something, and on the other side, the Receiver decodes the string sent based on the first character (# means the string is a setting, for example).
The problem is, after the first time both host and client sent something to one another, they can't seem to send again. No error, no message, no nothing. Just won't send. Is there something wrong with the sendingFunction? Or perhaps the delegate something? I don't know. Some advice would be appreciated, guys. And thanks in advance.
You're never calling BeginReceive again. The typical practice in async socket programming is to process the received data, then call BeginReceive again so that you can then process the next bit of data that comes in.

Categories