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));
Related
Im implementing a WebService with TCP. The webservice is the Server side that accept multiple clients. Is there any suggestions on how to configure a default port where to start the tcp clients? And with every client connected (aprox. 10 clients) will have an assigned port.
(I'm using Visual Studio 2010 the language is c#, Here is a code block for accepting the clients.)
Any suggestions will be accepted. Thanks!
private void StartListening(object sender, EventArgs e)
{
try
{
//Will move one the array of threads
index++;
//Will get the current IP Address
IPAddress ipaddr = IPAddress.Any;
//Port where the data will pass.
//First Port in use. 10,000
int Port = 10000;
if (true)
{
_TCPListener = new TcpListener(ipaddr, Port);
Port = Port + 1;
//Start Listening
_TCPListener.Start();
ThreadStart.Add(new ThreadStart(() => _TCPListener.BeginAcceptTcpClient(CompleteAcceptClient, _TCPListener)));
Thread.Add(new Thread(ThreadStart[index]));
Thread[index].Start();
}
else
{
_TCPListener = new TcpListener(ipaddr, Port + 2);
_TCPListener.Start();
ThreadStart delegateT = new ThreadStart(() => _TCPListener.BeginAcceptTcpClient(CompleteAcceptClient, _TCPListener));
Thread T = new Thread(delegateT);
T.Start();
}
}
catch(Exception ex)
{
throw ex;
}
}
//Here is the accept client method.
private void CompleteAcceptClient(IAsyncResult iar)
{
TcpListener tcpl = (TcpListener)iar.AsyncState;
try
{
ThreadStart delegateR = new ThreadStart(() => _TCPClient = tcpl.EndAcceptTcpClient(iar));
Thread R = new Thread(delegateR);
R.Start();
mRx = new byte[1024];
_TCPClient.GetStream().BeginRead(mRx, 0, mRx.Length, onCompleteReadFromTCPClientStream, _TCPClient);
}
catch(Exception e)
{
throw e;
}
}
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.
This is the first time I have used Windows Form application to do a socket server / client.
I have ran into a problem with my Socket.bind(IPEndpoint) under my public void Listen(). I get the error
Only one usage of each socket address (protocol/network address/port) is normally permitted
Any ideas how I could go about fixing this?
public Form1()
{
CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
}
Socket sck;
Socket acc;
IPEndPoint ipe;
List<Socket> lstClient = new List<Socket>();
Thread handleClient;
string myIP = "";
public void IP()
{
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress address in host.AddressList)
{
if (address.AddressFamily.ToString() == "InterNetwork")
{
myIP = address.ToString();
}
}
ipe = new IPEndPoint(IPAddress.Parse(myIP), 2001);
sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.IP);
}
private void btnListen_Click(object sender, EventArgs e)
{
this.Form1_Load(sender, e);
}
private void rtbMain_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = true;
}
private void Form1_Load(object sender, EventArgs e)
{
IP();
handleClient = new Thread(new ThreadStart(Listen));
handleClient.IsBackground = true;
handleClient.Start();
}
public void Listen()
{
sck.Bind(ipe);
sck.Listen(3);
while(true)
{
Socket acc=sck.Accept();
lstClient.Add(acc);
Thread clientProcess = new Thread(myThreadClient);
clientProcess.IsBackground = true;
clientProcess.Start(acc);
rtbMain.SelectionFont = new Font("Arial", 18, FontStyle.Bold);
rtbMain.SelectionColor = Color.Green;
rtbMain.AppendText("accept connections from" +
acc.RemoteEndPoint.ToString());
rtbMain.ScrollToCaret();
}
}
private void myThreadClient(object obj)
{
Socket clientACC = (Socket)obj;
while(true)
{
byte[] sizeBuf = new byte[1024];
int rec = clientACC.Receive(sizeBuf);
foreach (Socket acc in lstClient)
{
acc.Send(sizeBuf,sizeBuf.Length,SocketFlags.None);
}
}
}
This could happen if a socket is already listening in same port in your application any other process.
Just make sure no apps us it, and make sure you don't run multiple instances of your same application(verify it with taskmanager).
Aside:
Never use CheckForIllegalCrossThreadCalls = false
Have meaningful method names.
Your IP method doesn't makes sense to name it as IP. I'd rather name it as GetIPAndCreateSocket or something like that.
Method name should tell us what that method is going to do.
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?
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.