My problem is only happening when I try to use my socket connection under a windows service.
Basically I have a socket client which connect to a remote server.
When I use it in a client application I don't have any problem at all.
But when I try to use it under my windows service it doesn't work.
public abstract class SocketClient
{
public static readonly ILog log = LogManager.GetLogger(typeof(SocketClient));
private System.Net.Sockets.Socket fSocket;
private bool LocalsocketClientIsShutingDown;
private byte[] readbuf;
private byte[] sendbuf;
private string currentmessage = "";
public event EventHandler ConnectionDone;
public event EventHandler ConnectionFailed;
public event EventHandler MessageReceivingFailed;
public event EventHandler MessageSendingFailed;
public SocketClient()
{
log4net.Config.XmlConfigurator.Configure();
readbuf = new byte[16384];
this.ConnectionDone += new EventHandler(OnSocketConnectionDone);
this.ConnectionFailed += new EventHandler(OnSocketConnectionFailed);
this.MessageSendingFailed += new EventHandler(OnMessageSendingFailed);
this.MessageReceivingFailed += new EventHandler(OnMessageReceivingFailed);
}
public bool isConnected()
{
if (fSocket == null)
return false;
return fSocket.Connected;
}
protected abstract void OnSocketConnectionDone(object sender, EventArgs e);
protected abstract void OnSocketConnectionFailed(object sender, EventArgs e);
protected abstract void OnMessageSendingFailed(object sender, EventArgs e);
protected abstract void OnMessageReceivingFailed(object sender, EventArgs e);
protected void ConnectToServer(string ServerName, int Port)
{
try
{
log.Debug("SocketClient.ConnectToServer():" + ServerName);
if (this.fSocket == null || !this.fSocket.Connected)
{
this.fSocket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream
, ProtocolType.Tcp);
IPAddress[] ipadress;
log.Debug("ConnectToServer()1");
IPHostEntry he = Dns.GetHostEntry(ServerName); //Dns.Resolve(ServerName);
log.Debug("ConnectToServer()2" + he.HostName);
ipadress = he.AddressList;
//he.AddressList = he.AddressList.ToList().Where(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToArray();
IPEndPoint remoteEP = new IPEndPoint(ipadress[0], Port);
if (ServerName=="localhost")
{
IPHostEntry ipHostInfo = /*Dns.Resolve*/Dns.GetHostEntry(Dns.GetHostName()); //Dns.Resolve(Dns.GetHostName());
//dont take IPv6 IPs
//ipHostInfo.AddressList = ipHostInfo.AddressList.ToList().Where(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToArray();
IPAddress ipAddress = ipHostInfo.AddressList[0];
remoteEP = new IPEndPoint(ipAddress, Port);
}
log.Debug("ConnectToServer()3: start BeginConnect()");
this.fSocket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback)
, this.fSocket);
Trace.WriteLine("Connecting to server");
}
else
{
Trace.WriteLine("Already connected to a Server");
}
}
catch (Exception ex)
{
Trace.WriteLine("Error connecting to server" + ex.ToString());
OnConnectionFailed();
}
}
private void ConnectCallback(IAsyncResult asyncResult)
{
string[] obj;
try
{
log.Debug("end BeginConnect with ConnectCallback()");
System.Net.Sockets.Socket socket = (System.Net.Sockets.Socket)asyncResult.AsyncState;
this.fSocket = socket;
socket.EndConnect(asyncResult);
this.LocalsocketClientIsShutingDown = false;
this.fSocket.BeginReceive(this.readbuf, 0, this.readbuf.Length, SocketFlags.None
, new AsyncCallback(ReceiveCallback), this.fSocket);
OnConnectionDone();
}
catch (SocketException ex)
{
Trace.WriteLine("Connection Failed: " + ex.Message);
OnConnectionFailed();
}
}
private void OnConnectionDone()
{
log.Debug("OnConnectionDone");
if (ConnectionDone != null)
{
ConnectionDone(this, new EventArgs());
}
}
private void OnConnectionFailed()
{
log.Debug("OnConnectionFailed");
if (ConnectionFailed != null)
ConnectionFailed(this, new EventArgs());
}
public void SendMessage(string message)
{
log.Debug(">>> Sending Message: " + message);
if (this.fSocket != null && this.fSocket.Connected)
{
log.Debug(">>> Sending Message: Begin send 1:" + message);
//Turn string into byte for network transfer
this.sendbuf = Encoding.ASCII.GetBytes(message);
log.Debug(">>> Sending Message: Begin send 2:" + message);
this.fSocket.BeginSend(this.sendbuf, 0, this.sendbuf.Length, SocketFlags.None, new AsyncCallback(SendCallback)
, this.fSocket);
}
else
{
log.Debug("Cant Send Message: " + message + " _ Not connected to socket");
Trace.WriteLine("Not connected to Server");
}
}
private void SendCallback(IAsyncResult asyncResult)
{
try
{
//On récupere le socket sur lequel on a envoyé les données
System.Net.Sockets.Socket socket = (System.Net.Sockets.Socket)asyncResult.AsyncState;
//on met fin à l'envois de données
int senda = socket.ReceiveBufferSize;
int send = socket.EndSend(asyncResult);
Trace.WriteLine(">>> Message Sent: " + send + " bytes");
log.Debug(">>> Message Sent: " + send + " bytes");
}
catch (SocketException ex)
{
log.Debug("!!! Message NOT Sent: " + ex.Message);
Trace.WriteLine("!!! Message NOT Sent: " + ex.Message);
OnMessageSendingFailed();
}
}
private void OnMessageSendingFailed()
{
log.Debug("OnMessageSendingFailed");
if (MessageSendingFailed != null)
MessageSendingFailed(this, new EventArgs());
}
public void ReceiveMessage()
{
try
{
log.Debug(">>> ReceiveMessage");
if (this.fSocket != null && this.fSocket.Connected)
this.fSocket.BeginReceive(this.readbuf, 0, this.readbuf.Length, SocketFlags.None
, new AsyncCallback(ReceiveCallback), this.fSocket);
else
{
log.Debug("Not Connected to Server");
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
OnMessageReceivingFailed();
}
}
private void OnMessageReceivingFailed()
{
log.Debug("OnMessageReceivingFailed");
if (MessageReceivingFailed != null)
MessageReceivingFailed(this, new EventArgs());
}
private void ReceiveCallback(IAsyncResult asyncResult)
{
string[] obj;
log.Debug("ReceiveCallback");
try
{
System.Net.Sockets.Socket socket = (System.Net.Sockets.Socket)asyncResult.AsyncState;
log.Debug("ReceiveCallback 2" + socket.ToString());
int read = socket.EndReceive(asyncResult);
if (read > 0)
{
currentmessage += Encoding.ASCII.GetString(this.readbuf, 0, read);
log.Debug("ReceiveCallback 3" + currentmessage);
char _charEOL = '\n';
if (currentmessage[currentmessage.Length - 1] != _charEOL)
{
this.fSocket.BeginReceive(this.readbuf, 0, this.readbuf.Length, SocketFlags.None
, new AsyncCallback(ReceiveCallback), this.fSocket);
return;
}
readPacket(currentmessage.ToString());
obj = new string[] { "\n\n Server says :" + currentmessage };
currentmessage = "";
Buffer.SetByte(this.readbuf, 0, 0);
this.fSocket.BeginReceive(this.readbuf, 0, this.readbuf.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), this.fSocket);
}
if (read == 0 && !this.LocalsocketClientIsShutingDown)
{
this.fSocket.Close();
obj = new string[] { "Close Remote Socket" };
log.Debug("ReceiveCallback:Exception1-" + obj);
}
}
catch (SocketException ex)
{
obj = new string[1] { ex.Message };
log.Debug("ReceiveCallback:Exception2-" + ex.Message);
}
}
public void readPacket(string aMessage)
{
log.Debug("readPacket:"+aMessage);
try
{
string _formattedMsg = aMessage.Replace("\n", "");
string[] _tabAllMessages = _formattedMsg.Split(new char[] { '}' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i <= _tabAllMessages.Length - 1; i++)
{
_tabAllMessages[i] = _tabAllMessages[i] + "}";
//Trace.WriteLine("<<< Message Received: " + aMessage);
readSingleMessage(_tabAllMessages[i]);
}
}
finally
{
}
}
public abstract void readSingleMessage(string aMessage);//TO REDEFINE
public void Close()
{
log.Debug("SocketClient:Close");
try
{
if (this.fSocket != null && this.fSocket.Connected)
{
this.LocalsocketClientIsShutingDown = true;
//On ferme le socket
this.fSocket.Shutdown(SocketShutdown.Both);
System.Threading.Thread.Sleep(500);
//On détruit le socket
this.fSocket.Close();
Trace.WriteLine("Disconnected");
}
}
finally
{
}
}
The problem seems to come from that line in ConnectCallBack():
this.fSocket.BeginReceive(this.readbuf, 0, this.readbuf.Length, SocketFlags.None
, new AsyncCallback(ReceiveCallback), this.fSocket);
I dont have any problem with that in a client application.
But when I use the socket in a windows service, it seems that if I keep that line, I will get a socket error a bit later.
If I dont keep the line, then both client and windows service wont be able to listen for some messages to read.
I m a bit lost as I used my windows application for a few month and never had an issue before I tried to turn it into a windows service.
Thanks!
EDIT: a few logs:
DEBUG2014-10-02 00:01:27 – Start Session
DEBUG2014-10-02 00:01:27 – Windows Service: Start Login
DEBUG2014-10-02 00:01:27 – ImgSocketClient:ConnectToServerAndSendPassword():xxxxxxxxx.com_23459
DEBUG2014-10-02 00:01:27 – SocketClient.ConnectToServer():xxxxxxxxx.com
DEBUG2014-10-02 00:01:27 – ConnectToServer()3: start BeginConnect()
DEBUG2014-10-02 00:01:27 – end BeginConnect with ConnectCallback()
DEBUG2014-10-02 00:01:27 – OnConnectionDone
DEBUG2014-10-02 00:01:28 – >>> Socket Connected - Sending Password
DEBUG2014-10-02 00:01:29 – >>> Sending Message: PASSWORD:xxx
DEBUG2014-10-02 00:01:29 – >>> Message Sent: 25 bytes
DEBUG2014-10-02 00:01:29 – ReceiveCallback
DEBUG2014-10-02 00:01:29 – **ReceiveCallback:Exception1-System.String[]**
DEBUG2014-10-02 00:01:29 – >>> Password Sent
DEBUG2014-10-02 00:01:29 – >>> Send Message to suscribe to updates
DEBUG2014-10-02 00:01:29 – >>> Sending Message: REQUEST:aaaaa
DEBUG2014-10-02 00:01:29 – Cant Send Message: REQUEST:aaaaa_ Not connected to socket
The problem is in lines:
if (read == 0 && !this.LocalsocketClientIsShutingDown)
{
this.fSocket.Close();
obj = new string[] { "Close Remote Socket" };
log.Debug("ReceiveCallback:Exception1-" + obj);
}
It is normal if You receive 0 bytes. Why did you close the socket in this case? After closing the socket you can't send the message "REQUEST:aaaaa"...
Remove these lines and try again.
Related
I'm trying to make my code accept two or more clients to my server program. Here is the code. I need help with the code on how to accept multiple clients at the same time. I got an error with the port. It says "Only one usage of each socket address (protocol/network address/port) is normally permitted"
namespace TCPServer
{
public partial class Form1 : Form
{
//Create TCP/IP Socket
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
TcpListener mTCPListener;
TcpClient mTCPClient = new TcpClient();
NetworkStream serverStream;
byte[] mRx;
public Form1()
{
InitializeComponent();
}
void onCompleteAcceptTcpClient(IAsyncResult iar)
{
TcpListener tcpl = (TcpListener)iar.AsyncState;
try
{
ThreadStart delegateR = new ThreadStart(() =>
mTCPClient = tcpl.EndAcceptTcpClient(iar));
Thread R = new Thread(delegateR);
R.Start();
printLine("Client Connected...");
//Begin Asynchronous Read
mRx = new byte[1024];
mTCPClient.GetStream().BeginRead(mRx, 0, mRx.Length, onCompleteReadFromTCPClientStream, mTCPClient);
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void btnStartListening_Click_1(object sender, EventArgs e)
{
try
{
IPAddress ipaddr;
int nPort = 23000;
#region Validating IP Address
//if (!int.TryParse(tbPort.Text, out nPort))
//{
// nPort = 23000;
//}
if (!IPAddress.TryParse(tbIPAddress.Text, out ipaddr))
{
MessageBox.Show("Invalid IP address supplied.");
return;
}
#endregion
mTCPListener = new TcpListener(ipaddr, nPort);
//Start Listening
mTCPListener.Start();
//ThreadStart delegateT = new ThreadStart(() => { RefreshLot(lotId); });
//Thread T = new Thread(delegateT);
//T.Start();
ThreadStart delegateT = new ThreadStart(() => mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener));
Thread T = new Thread(delegateT);
T.Start();
//Begin accept tcp client (only one)
//mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener));
if (mTCPListener.Pending())
{
nPort = nPort + 1;
mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener);
}
}
catch (Exception ex)
{
throw ex;
}
}
void onCompleteReadFromTCPClientStream(IAsyncResult iar)
{
TcpClient tcpc;
int nCountReadBytes = 0;
string strRecv;
try
{
tcpc = (TcpClient)iar.AsyncState;
nCountReadBytes = tcpc.GetStream().EndRead(iar);
if (nCountReadBytes == 0)
{
MessageBox.Show("Client disconnected.");
return;
}
strRecv = Encoding.ASCII.GetString(mRx, 0, nCountReadBytes);
printLine(strRecv);
mRx = new byte[1024];
tcpc.GetStream().BeginRead(mRx, 0, mRx.Length, onCompleteReadFromTCPClientStream, tcpc);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
public void printLine(string _strPrint)
{
tbConsoleOutput.Invoke(new Action<string>(doInvoke), _strPrint);
}
public void doInvoke(string _strPrint)
{
tbConsoleOutput.Text = _strPrint + Environment.NewLine + tbConsoleOutput.Text;
}
private void onCompleteWriteToClientStream(IAsyncResult iar)
{
try
{
TcpClient tcpc = (TcpClient)iar.AsyncState;
tcpc.GetStream().EndWrite(iar);
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void btnSend_Click_1(object sender, EventArgs e)
{
byte[] tx = new byte[1024];
if (string.IsNullOrEmpty(tbPayload.Text)) return;
try
{
if (mTCPClient != null)
{
if (mTCPClient.Client.Connected)
{
//This is the message that will be sent
tx = Encoding.ASCII.GetBytes("Server MESRII sent: " + tbPayload.Text + " " + DateTime.Now);
mTCPClient.GetStream().BeginWrite(tx, 0, tx.Length, onCompleteWriteToClientStream, mTCPClient);
}
}
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void btnStartListening2_Click(object sender, EventArgs e)
{
}
}
You should create single TcpListener on your server, besause only one listener can use one port.
When you getting new connection (AcceptTcpClient method), you may begin new thread for messaging exchange with client.
You can see good examples in this question
I was working in the code and took all the suggestions provided. What I did was Call the Start listening this way...
`private void btnStartListening_Click_1(object sender, EventArgs e)
{
try
{
index++;
IPAddress ipaddr = IPAddress.Any;
int x = Convert.ToInt32(tbPort.Text);
int nPort = x;
//#region Validating IP Address
//if (!int.TryParse(tbPort.Text, out nPort))
//{
// nPort = 23000;
//}
//if (!IPAddress.TryParse(tbIPAddress.Text, out ipaddr))
//{
// MessageBox.Show("Invalid IP address supplied.");
// return;
//}
//#endregion
if (nPort >= 23000)
{
nPort = nPort + 1;
mTCPListener = new TcpListener(ipaddr, nPort);
//Start Listening on port nPort + 1
mTCPListener.Start();
testingThreadStart.Add(new ThreadStart(() => mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener)));
//ThreadStart delegateT = new ThreadStart(() => mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener));
testingThread.Add(new Thread(testingThreadStart[index]));
//Thread T = new Thread(delegateT);
//T.Start();
testingThread[index].Start();
//Begin accept tcp client (only one)
//mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener));
}
else
{
mTCPListener = new TcpListener(ipaddr, nPort + 1);
//Start Listening on port 23000
mTCPListener.Start();
ThreadStart delegateT = new ThreadStart(() => mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener));
Thread T = new Thread(delegateT);
T.Start();
}
}`
Also added list of threads on the beginning of the code...
List<ThreadStart> testingThreadStart = new List<ThreadStart>();
List<Thread> testingThread = new List<Thread>();
and thats how it worked. If anyone need/want the complete code, I can post it. For future examples.
So I am creating a socket based web chat using C#. This is a school project.
It is basic server-client chat -> client sends message to server, server "broadcast" == sends message to all connected clients.
However if I connect two clients, and send message from one to another I only get something like:
▯▯▯▯▯▯▯▯▯▯
When I press "SEND" again (with the same message), it turns out good.
This is function for receiving.. I use it in Thread.
public void wait()
{
byte[] bytes = new byte[1024];
while (!shutdown)
{
// if (shutdown) break;
try
{
int bytesRec = senderSocket.Receive(bytes);
Dispatcher.Invoke(new Action(() =>
{
output.Text += "\n" + Encoding.UTF8.GetString(bytes, 0, bytesRec);
if (scroll.VerticalOffset == scroll.ScrollableHeight)
{
scroll.ScrollToEnd();
}
}));
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
}
This is for sending: (LCP is my own "protocole".. ignore this, it just adds one letter to string)
private void send_Click(object sender, RoutedEventArgs e)
{
try
{
LCP protocol = new LCP();
string messg = user.Text + " pravi: " + message.Text ;
string messag = protocol.CreateMessage(messg, "M");
byte[] msg = Encoding.UTF8.GetBytes(messag);
// Send the data through the socket.
senderSocket.Send(msg);
// int bytesRec = senderSocket.Receive(bytes);
//output.Text += "\n" + Encoding.UTF8.GetString(bytes, 0, bytesRec);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
and this is how I handle things on server:
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
while (true)
{
Socket handler = listener.Accept();
data = null;
users.Add(handler.RemoteEndPoint);
socks.Add(handler);
new Thread(new ThreadStart(() =>
{
while (true)
{
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
data = Encoding.UTF8.GetString(bytes, 0, bytesRec);
LCP protocolParser = new LCP();
Dictionary<string, string> wholeMessage = protocolParser.ParseMessage(data);
if (wholeMessage["type"] == "$J")
{
Console.WriteLine("\nPridružil se je " + wholeMessage["message"]);
byte[] msg = Encoding.UTF8.GetBytes(wholeMessage["message"] + " se je pridružil");
foreach (Socket edp in socks)
{
edp.Send(msg);
//handler.SendTo(msg,edp);
}
}
// Show the data on the console.
else if (wholeMessage["type"] == "$Q")
{
handler.Shutdown(SocketShutdown.Receive);
handler.Close();
socks.Remove(handler);
break;
}
else
{
Console.WriteLine("\n" + wholeMessage["message"]);
byte[] msg = Encoding.UTF8.GetBytes(wholeMessage["message"]);
// Dispatcher.Invoke(new Action(() =>
//{
foreach (Socket edp in socks)
{
edp.Send(msg);
//handler.SendTo(msg,edp);
}
// }));
}
}
//tvoja koda
})
){IsBackground=true}.Start();
// An incoming connection needs to be processed.
// Echo the data back to the client.
}
}
I have solved this using TcpListener and TcpClient class.
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?
I have developed UDP multicast server in c# and UDP multicast reciever in Android,but iam not able to recieve data from server to client(Android).Is it because of the port numbers
i have used in code ? Your help is greatly appretiated and will save me nights.
***Server code
namespace Server
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
UdpClient udpclient = new UdpClient();
IPAddress multicastaddress = IPAddress.Parse("233.45.17.10");
udpclient.JoinMulticastGroup(multicastaddress);
IPEndPoint remoteep = new IPEndPoint(multicastaddress, 10000);
Byte[] buffer = null;
for (int i=1;i<30;i++)
{
buffer = Encoding.Unicode.GetBytes(i.ToString());
int flag = udpclient.Send(buffer, buffer.Length, remoteep);
}
MessageBox.Show("Data Sent TO " + ip.Text + "On Port " + port.Text);
status.Text = "Connected";
}
private void disconnect_Click(object sender, EventArgs e)
{
this.Close();
}
}
}***
Client code(Android):
public class TestMulticast extends Activity
{
static boolean done = false;
EditText et;
TextView tv;
Button b;
MulticastSocket socket;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
b=(Button)findViewById(R.id.b);
et=(EditText)findViewById(R.id.et);
tv =(TextView)findViewById(R.id.tv);
b.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View v)
{
try
{
String msg = et.getText().toString();
socket.send(new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, InetAddress.getByName("192.168.1.6"), 10000));
Toast.makeText(getApplicationContext(), "sent", 100).show();
}
catch (Exception e)
{
e.printStackTrace();
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
if (!done)
{
try
{
WifiManager wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiinfo = wifiManager.getConnectionInfo();
int intaddr = wifiinfo.getIpAddress();
if (intaddr == 0)
{
tv.setText("Unable to get WIFI IP address");
}
else
{
byte[] byteaddr = null;
byteaddr = new byte[] {
(byte)(intaddr & 0xff),
(byte)(intaddr >> 8 & 0xff),
(byte)(intaddr >> 16 & 0xff),
(byte)(intaddr >> 24 & 0xff)
};
String machineName = "androidtestdevice";
InetAddress addr = InetAddress.getByAddress(machineName, byteaddr);
tv.append("Using address: " + addr + "\n");
Toast.makeText(getApplicationContext(), "using address"+addr, 50).show();
// create socket
socket = new MulticastSocket(11111);
// set network interface
NetworkInterface iface = NetworkInterface.getByInetAddress(addr);
Toast.makeText(getApplicationContext(), "First address on interface is: " + getAddressFor(iface), 50).show();
tv.append("First address on interface is: " + getAddressFor(iface) + "\n");
// The following line throws an exception in Android (Address is not available)
// If it's not called, the socket can receives packets
// Equivalent code in seems to C work.
//socket.setNetworkInterface(iface);
// join group
socket.joinGroup(InetAddress.getByName("233.45.17.10"));
tv.append("It worked\n");
// start receiving
new DatagramListener(socket, tv).start();
}
}
catch (Exception e) {
tv.append(e.toString() + "\n");
e.printStackTrace();
}
}
}
class DatagramListener extends Thread {
private DatagramSocket socket;
private TextView tv;
DatagramListener(DatagramSocket s, TextView tv) {
socket = s;
this.tv = tv;
}
public void run() {
byte[] buf = new byte[1000];
try {
while (true) {
DatagramPacket recv = new DatagramPacket(buf, buf.length);
socket.receive(recv);
System.out.println("received: " + new String(recv.getData(), recv.getOffset(), recv.getLength()));
runOnUiThread(new MyRunnable(new String(recv.getData(), recv.getOffset(), recv.getLength()), tv));
Toast.makeText(getApplicationContext(), "Now showing data", Toast.LENGTH_SHORT).show();
}
}
catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "received: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}
static private class MyRunnable implements Runnable {
private TextView tv;
private String text;
public MyRunnable(String text, TextView tv) {
this.tv = tv;
this.text = text;
}
public void run() {
tv.append(text + "\n");
}
}
public static InetAddress getAddressFor(NetworkInterface iface) {
Enumeration<InetAddress> theAddresses = iface.getInetAddresses();
boolean found = false;
InetAddress firstAddress = null;
while ((theAddresses.hasMoreElements()) && (found != true)) {
InetAddress theAddress = theAddresses.nextElement();
if (theAddress instanceof Inet4Address) {
firstAddress = theAddress;
found = true;
}
}
return firstAddress;
}
}
Multicast packets are filtered in many android devices depending on vendor (some do others don't htc would filter it most likely), presumably to save battery. it is not blocked in android as such but the vendors.
I have a c# socket based server which serves TCP clients.
I use telnet based monitoring to see if the server is listening.
to versify clients are up i use server keep alive (sending a random string data), and if socket expection raises-i remove the client from a client's dictionary.
the probelm is: the telnet connections to the socket doesn't get removed from the list of connections and the number of clients is rising up slowly but surely.
i tried a telnet manually to the server through command line and than closing the telnet connection-nothing.the server just keep sending the keep alive to the telnet connection with no execptions.
this is my read call back:
protected void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the async state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.socket;
if (state.socket == null)
return;
if (!state.socket.Connected)
return;
int id = state.id;
try
{
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
string newAddedStr = string.Empty;
newAddedStr = Encoding.UTF8.GetString(state.buffer, 0, bytesRead);
//cut the new message and add it
if (state.sb == null)
state.sb = new StringBuilder();
state.sb.Append(newAddedStr);
// There might be more data, so store the data received so far.
//add data until end of XML
content = state.sb.ToString();
//IF GOT FULL MESSAGE FROM SOCKET
if ((content.Length > 0) /*&& (content.IndexOf("\0") > -1)*/)
{
String strh = String.Format("Client # {0} data: ", id);
strh += content.Replace("\0", "");
if (!strh.Contains("keepalive"))
LogWriter.Trace(strh, "");
// l(writeToGetTextBoxMsg), new object[] { strh });
if (state != null)
{
if (state.sb == null)
state.sb = new StringBuilder();
state.sb.Length = 0;
}
//add the rest of the xml
string objData = content.Replace("\0", "");
string xmlData = objData.ToString();
try
{
if (xmlData.Contains("Unsubscribe"))
{
RemoveSubscriber(xmlData);
}
else
{
if (xmlData.Contains("Subscribe"))
{
if (!state.IsInitiated)
{
state.Init();
state.socketClient.OnSocketError += new SocketErrorHandler(socketClient_OnSocketError);
state.socketClient.clientSocket = handler;
}
AddSubscriber(xmlData, state);
}
}
xmlData = null;
objData = null;
content = null;
}
catch (ArgumentOutOfRangeException ex)
{
LogWriter.Trace(newAddedStr,"ArgumentOutOfRangeException in ReadCallback");
}
catch (Exception ex)
{
LogWriter.TraceError(ex.Message + " " + ex.StackTrace + " " + newAddedStr);
}
#region oldCode
#endregion
}
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(this.ReadCallback), state);
}
}
catch (System.Net.Sockets.SocketException es)
{
closeSocket(state, false, "Execption:" + es.Message + "," + es.StackTrace);
if (es.ErrorCode != 64)
{
LogWriter.Trace(string.Format("Socket Exception: {0}, {1}.", es.ErrorCode, es.ToString()), "");
}
}
catch (Exception e)
{
closeSocket(state, false,"Execption:"+e.Message+","+e.StackTrace);
if (e.GetType().FullName != "System.ObjectDisposedException")
{
Console.WriteLine("Exception: " + e.StackTrace);
LogWriter.Trace("Exception Message: " + e.ToString() + e.StackTrace, "");
Console.WriteLine("Exception Message: " + e.ToString());
LogWriter.Trace("ReadCallback:" + e.Message + " " + e.StackTrace, "ERROR");
}
}
}
any ideas?
When you do a read of a socket and 0 is returned you know that the other side of the connection has closed. Are you doing that?