Android TCP communication error - c#

I am very new to Android Programming .
My code in android is as follows
public class AndroidClient extends Activity {
EditText textOut;
TextView textIn;
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_client);
textOut = (EditText)findViewById(R.id.textout);
Button buttonSend = (Button)findViewById(R.id.send);
textIn = (TextView)findViewById(R.id.textin);
buttonSend.setOnClickListener(buttonSendOnClickListener);
}
Button.OnClickListener buttonSendOnClickListener
= new Button.OnClickListener(){
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
new BackgroundDataTask().execute("");
}};
public class BackgroundDataTask extends AsyncTask<String,String,String> {
private Exception ex;
#Override
protected String doInBackground(String... urls) {
try {
socket = new Socket("10.20.50.68", 8888);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF(textOut.getText().toString());
textIn.setText(dataInputStream.readUTF());
socket = serverSocket.accept();
textIn.setText(socket.getInetAddress().toString());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
if (socket != null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataOutputStream != null){
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataInputStream != null){
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return "";
}
}
}
I have a server in C# Code
The code listens to the port and writes the output
However this only works for the first time when I type in the text and click Send the code is received at Server end and I can see the ouptput in the console,But the value is not received after that .So how can i keep this socket running ? What am I missing?
Thank you All

try this
create a class client.java
public class client{
Socket socket;
int Port;
InetAddress serverIp;
public boolean connection;
public client(String ip, int port) {
// TODO Auto-generated constructor stub
try {
serverIp = InetAddress.getByName(ip);
Port = port;
connect();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
connection = false;
}
}
public void connect(){
try {
System.out.println("wait connection client "+serverIp+" "+Port);
socket = new Socket(serverIp, Port);
connection = true;
} catch (IOException e) {
//e.printStackTrace();
connection = false;
}
}
public boolean send(String message) throws IOException {
byte[] data=message.getBytes();
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
int len = data.length;
dos.writeInt(len);
if (len > 0) {
dos.write(data, 0, len);
}
return true;
}
public String read() {
InputStream in = null;
try {
in = socket.getInputStream();
} catch (IOException e) {
connection=false;
e.printStackTrace();
}
DataInputStream dis = new DataInputStream(in);
try {
int len = dis.readInt();
byte[] data = new byte[len];
if (len > 0) {
dis.readFully(data);
}
String result = new String(data, 0, data.length);
return result;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
connection=false;
}
return "";
}
and create a object of client.java in your activity onCreate
client con=new client("10.20.50.68", 8888);
and use con.send("your_data") to sent and String data=con.read(); to receive data...
if you want asynchronous listening of data in socket, use thread

Related

Socket using. Data is not sending on the second time

Issue description.
I sending and receiving data. When i launch program, data who i send and receive, displayed is right. If relaunch program in 1 minutes, no more, data send and receive displayed is currect.
BUT! IF i relaunching program more then after 2 minutes, FIRST receiving and sending displayed is right, BUT SECOND sending and receiving data, is not displayed (((
What's happening, and how i fix this???
Thanks for any help!
public override bool Connect()
{
try
{
if (NetClient != null)
{
NetClient.Close();
}
NetClient = new Socket(ConnectionPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = NetClient.BeginConnect(ConnectionPoint, null, null);
bool success = result.AsyncWaitHandle.WaitOne(connectionDelay, false/*true*/);
if (NetClient.Connected)
{
Log("report.log", string.Format("Connection OK"));
return true;
}
Log("report.log", string.Format("NetClient is not connected"));
}
catch (Exception e)
{
MessageBox.Show(e.Message);
Log("report.log", string.Format("NetClient error while connecting: {0}", e.Message));
}
return false;
}
public override bool Send(byte[] data)
{
try
{
if (NetClient.Connected)
{
NetClient.SendTo(data, ConnectionPoint);
Thread.Sleep(transferDelay);
return true;
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
return false;
}
public override string Receive(int length)
{
byte[] data = new byte[bufferSize]; // bufferSize = i tryed any buffer from 5 bytes to 16384 bytes
string strbuff = "";
try
{
if (NetClient.Connected)
{
do
{
IAsyncResult result = NetClient.BeginReceive(data, 0, bufferSize, SocketFlags.None, null, null);
bool success = result.AsyncWaitHandle.WaitOne(connectionDelay, true);
int receivedBytesCount = NetClient.EndReceive(result);
if (receivedBytesCount == 0)
{
receivedBytesCount = 0;
}
strbuff += Encoding.ASCII.GetString(data, 0, receivedBytesCount);
} while (NetClient.Available > 0);
if (NetClient != null && NetClient.Connected)
{
NetClient.Shutdown(SocketShutdown.Both);
NetClient.Close();
}
return strbuff;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return null;
}
public override void Disconnect()
{
try
{
if (NetClient.Connected)
{
NetClient.Shutdown(SocketShutdown.Both);
NetClient.Close();
}
else
{
if (NetClient != null)
{
NetClient.Close();
}
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}

c# How to accept multiple clients in one tcp server

I'm writing a code in c# to have a tcp server that accepts multiple client at the same time. How can I implemet that in my code?
Here is my code, it's in form code. I have a button to start listening, and only accepts one client.
Pd: I'm using Visual Studio 2010.
public partial class Form1 : Form
{
TcpListener mTCPListener;
TcpClient mTCPClient = new TcpClient();
NetworkStream serverStream;
byte[] mRx;
public Form1()
{
InitializeComponent();
}
void onCompleteAcceptTcpClient(IAsyncResult iar)
{
TcpListener tcpl = (TcpListener)iar.AsyncState;
try
{
mTCPClient = tcpl.EndAcceptTcpClient(iar);
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);
}
}
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 btnStartListening_Click_1(object sender, EventArgs e)
{
try
{
IPAddress ipaddr;
int nPort;
#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();
mTCPListener.BeginAcceptTcpClient(onCompleteAcceptTcpClient, mTCPListener);
}
catch (Exception ex)
{
throw ex;
}
}
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)
{
tx = Encoding.ASCII.GetBytes(tbPayload.Text);
mTCPClient.GetStream().BeginWrite(tx, 0, tx.Length, onCompleteWriteToClientStream, mTCPClient);
}
}
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}

Multiple Clients in Client Server app in C#

using resources at http://www.developerfusion.com i came up with the following server code. It works well for single client. How can i make it for multiple clients. I tried adding array and different instances of the beiginreceive but was unable to. The server code:
class Program
{
public static AsyncCallback pfnWorkerCallBack;
public static Socket m_socListener;
public static Socket m_socWorker;
static void Main(string[] args)
{
try
{
//create the listening socket...
m_socListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, 8221);
//bind to local IP Address...
m_socListener.Bind(ipLocal);
Console.WriteLine("UCManager Started");
//start listening...
m_socListener.Listen(4);
// create the call back for any client connections...
m_socListener.BeginAccept(new AsyncCallback(OnClientConnect), null);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadLine();
}
public static void OnClientConnect(IAsyncResult asyn)
{
try
{
m_socWorker = m_socListener.EndAccept(asyn);
WaitForData(m_socWorker);
}
catch (Exception se)
{
Console.WriteLine(se.Message);
}
}
public class CSocketPacket
{
public System.Net.Sockets.Socket thisSocket;
public byte[] dataBuffer = new byte[1];
}
public static void WaitForData(System.Net.Sockets.Socket soc)
{
try
{
if (pfnWorkerCallBack == null)
{
pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
}
CSocketPacket theSocPkt = new CSocketPacket();
theSocPkt.thisSocket = soc;
// now start to listen for any data...
soc.BeginReceive(theSocPkt.dataBuffer, 0, theSocPkt.dataBuffer.Length, SocketFlags.None, pfnWorkerCallBack, theSocPkt);
}
catch (SocketException se)
{
Console.WriteLine(se.Message);
}
}
public static void OnDataReceived(IAsyncResult asyn)
{
try
{
CSocketPacket theSockId = (CSocketPacket)asyn.AsyncState;
//end receive...
int iRx = 0;
iRx = theSockId.thisSocket.EndReceive(asyn);
char[] chars = new char[iRx + 1];
Decoder d = Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
String szData = new String(chars);
Console.WriteLine(szData);
int code = Convert.ToInt32(szData);
WaitForData(m_socWorker);
}
catch (Exception se)
{
Console.WriteLine(se.Message);
}
}
}
}
EDIT: Ok i did something on the lines of Async TCP Server for multiple Clients.
public static void OnClientConnect(IAsyncResult asyn)
{
try
{
Socket m_socWorkerInstance = m_socListener.EndAccept(asyn);
clientSocketList.Add(m_socWorkerInstance);
WaitForData(m_socWorkerInstance);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n");
}
catch (SocketException se)
{
Console.WriteLine(se.Message);
}
}
public static void WaitForData(System.Net.Sockets.Socket soc)
{
try
{
if (pfnWorkerCallBack == null)
{
pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
}
CSocketPacket theSocPkt = new CSocketPacket();
theSocPkt.thisSocket = soc;
// now start to listen for any data...
soc.BeginReceive(theSocPkt.dataBuffer, 0, theSocPkt.dataBuffer.Length, SocketFlags.None, pfnWorkerCallBack, theSocPkt);
m_socListener.BeginAccept(new AsyncCallback(OnClientConnect), null);
}
catch (SocketException se)
{
Console.WriteLine(se.Message);
}
}
Now i am able to connect two clients but not able to communicate ...I am unable to send message from server to client...any suggestions...also should i have different read functions for both clients if i connect with two client???
You call BeginAccept only once, so after one client has been accepted, your server won't accept any new connections. You should call BeginAccept again after accepting a connection.
Ok i was able to solve it using Async TCP Server for multiple Clients:
public static void OnClientConnect(IAsyncResult asyn)
{
try
{
Socket m_socWorkerInstance = m_socListener.EndAccept(asyn);
clientSocketList.Add(m_socWorkerInstance);
WaitForData(m_socWorkerInstance);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n");
}
catch (SocketException se)
{
Console.WriteLine(se.Message);
}
}
public static void WaitForData(System.Net.Sockets.Socket soc)
{
try
{
if (pfnWorkerCallBack == null)
{
pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
}
CSocketPacket theSocPkt = new CSocketPacket();
theSocPkt.thisSocket = soc;
// now start to listen for any data...
soc.BeginReceive(theSocPkt.dataBuffer, 0, theSocPkt.dataBuffer.Length, SocketFlags.None, pfnWorkerCallBack, theSocPkt);
m_socListener.BeginAccept(new AsyncCallback(OnClientConnect), null);
}
catch (SocketException se)
{
Console.WriteLine(se.Message);
}
}

Send data from android to C#

I want to send data from android to C#. C# is server. Android is client
I connect my computer to mobile's hotspot but i receive this error:
failed to connect to 192.168.1.15(port 4444):connect failed:ENETUNREACH(Network is unreachable
Here is the java code:
public class MainActivity extends Activity {
//TextView tv=(TextView) findViewById(R.id.textView2);
EditText edittext1;
private TCPClient mTcpClient;
private Button btnIP;
private TextView txt1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt1 = (TextView) findViewById(R.id.textView1);
final EditText editText = (EditText)findViewById(R.id.edit_message);
edittext1=(EditText) findViewById(R.id.editText1);
btnIP=(Button) findViewById(R.id.button1);
Button bt2=(Button) findViewById(R.id.button2);
bt2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
txt1.setText(TCPClient.log) ;
}
});
Button send = (Button)findViewById(R.id.send_button);
// connect to the server
new connectTask().execute("");
btnIP.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
TCPClient.SERVERIP=edittext1.getText().toString();
new connectTask().execute("");
}
});
send.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View view) {
String message = editText.getText().toString();
//sends the message to the server
if (mTcpClient != null)
{
mTcpClient.sendMessage(message);
}
editText.setText("");
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public class connectTask extends AsyncTask<String,String,TCPClient>
{
#Override
protected TCPClient doInBackground(String... message)
{
mTcpClient = new TCPClient(new OnMessageReceived()
{
#Override public void messageReceived(String message)
{
publishProgress(message);
}
});
Looper.prepare();
mTcpClient.run();
return null;
}
#Override
protected void onProgressUpdate(String... values)
{
super.onProgressUpdate(values);
}
}
public static class TCPClient
{
private String serverMessage;
public static String SERVERIP = "192.168.1.15";
public static final int SERVERPORT = 4444;
private OnMessageReceived mMessageListener = null;
public static String log="";
private boolean mRun = false;
PrintWriter out;
BufferedReader in;
DataOutputStream dataOutputStream = null;
//OutputStream os;
public TCPClient(OnMessageReceived listener)
{
mMessageListener = listener;
}
public void sendMessage(String message)
{
if (out != null && !out.checkError())
{
/* String toSend = "a"; byte[] toSendBytes = toSend.getBytes();
int toSendLen = toSendBytes.length; byte[] toSendLenBytes = new byte[4];
toSendLenBytes[0] = (byte)(toSendLen & 0xff); toSendLenBytes[1] = (byte)((toSendLen >> 8) & 0xff); toSendLenBytes[2] = (byte)((toSendLen >> 16) & 0xff); toSendLenBytes[3] = (byte)((toSendLen >> 24) & 0xff); try { os.write(toSendLenBytes); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } try { os.write(toSendBytes);
} catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } */
out.print(message);
out.flush();
}
}
public void stopClient()
{
mRun = false;
}
public void run()
{
// TextView tv=(TextView) findViewById(R.id.textView2);
//tv.setText(tv.getText()+"\n"+ "run");
mRun = true;
try
{
InetAddress serverAddr = InetAddress.getByName(SERVERIP);
Log.e("TCP Client", "C: Connecting...");
log="C: Connecting...";
//Toast.makeText(MainActivity.this, "Connecting", Toast.LENGTH_SHORT).show();
//tv.setText(tv.getText()+"\n"+ "Connecting");
//tv.setText(tv.getText()+"\n"+ "Connecting...");
Socket socket = new Socket(serverAddr, SERVERPORT);
/// //os = socket.getOutputStream();
if(socket.isBound())
{
Log.i("SOCKET", "Socket: Connected");
log="Connected";
//tv.setText(tv.getText()+"\n"+ "Connected");
//Toast.makeText(MainActivity.this, "Connected", Toast.LENGTH_SHORT).show();
//tv.setText(tv.getText()+"\n"+ "Connected");
}
else{
Log.e("SOCKET", "Socket: Not Connected");
log="Not Connected";
// tv.setText(tv.getText()+"\n"+ "not Connected");
//Toast.makeText(MainActivity.this, "not Connected", Toast.LENGTH_SHORT).show();
//tv.setText(tv.getText()+"\n"+ " Not Connected");
} try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
//out.println(new char[]{'h','e'});
//out.flush();
/* dataOutputStream = new DataOutputStream(socket.getOutputStream()); byte[] bytes = new byte[] {1};
* dataOutputStream.write(bytes, 0, bytes.length); */
Log.e("TCP Client", "C: Sent.");
log=" Sent";
Log.e("TCP Client", "C: Done.");
log=" Done";
if(out.checkError())
{
Log.e("PrintWriter", "CheckError");
}
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (mRun)
{
serverMessage = in.readLine();
if (serverMessage != null && mMessageListener != null)
{
mMessageListener.messageReceived(serverMessage);
}
serverMessage = null;
}
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + serverMessage + "'");
} catch (Exception e) { Log.e("TCP", "S: Error", e); }
finally { socket.close(); }
}
catch (Exception e) { Log.e("TCP", "C: Error", e);
log=e.getMessage();
//tv.setText(tv.getText()+"\n"+ e.getMessage());
}
}
}
}
C# code:
class Program
{
static private IPAddress getLocalIPAddress()
{
IPHostEntry host;
//string localIP = "";
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
// localIP = ip.ToString();
return ip;
//break;
}
}
// return localIP;
return null;
}
static void Main(string[] args)
{
int recv;
byte[] data = new byte[2048];
IPEndPoint ipep = new IPEndPoint(getLocalIPAddress(), 4444);
Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
newsock.Bind(ipep);
newsock.Listen(10);
Console.WriteLine("Waiting for a client...");
Socket client = newsock.Accept();
IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port{1}", clientep.Address, clientep.Port);
string welcome = "Welcome to my test server";
data = Encoding.ASCII.GetBytes(welcome);
client.Send(data, data.Length, SocketFlags.None);
while (true)
{
data = new byte[1024];
recv = client.Receive(data);
if (recv == 0)
break;
Console.WriteLine(Encoding.ASCII.GetString(data, 0,
recv));
client.Send(data, recv, SocketFlags.None);
}
Console.WriteLine("Disconnected from{0}", clientep.Address);
client.Close();
newsock.Close();
}
}

Asynchronous socket, forced disconnection and reuse

Im writing an application which is going to act as a tcp listener for a single client. The client is a java applet and will periodically connect to the listener, send some data and then wait for a response.
The code for the TcpServer class below has been largely lifted from an example provided by a more knowledgeable stackoverflow member in response to a different question.
Everything was going great until I found something in testing which wasnt mentioned in any of the interface documents I have. After the server has responded to the client it must then disconnect the client and start listening again.
My first thought was to call Disconnect() from inside SendData() but this results in a call to ReceiveCompleted() from somewhere and a nasty exception about the socket already being disposed.
Is this requirement easily achievable with the code design I have, and will I run into any problems in reusing the socket for subsequent connections?
sealed class TcpServer : IDisposable
{
#region Fields
private const int SocketBufferSize = 1024;
private readonly TcpListener tcpListener;
private Socket connectedSocket;
private bool disposed = false;
#endregion Fields
#region Constructors
public TcpServer(int port)
{
tcpListener = new TcpListener(IPAddress.Any, port);
tcpListener.Start();
tcpListener.BeginAcceptSocket(EndAcceptSocket, tcpListener);
}
~TcpServer()
{
Dispose(false);
}
#endregion Constructors
#region Events
public event EventHandler<DataReceivedEventArgs> DataReceived;
public event EventHandler<IPEndPointEventArgs> SocketConnected;
public event EventHandler<IPEndPointEventArgs> SocketDisconnected;
#endregion Events
#region Methods
public void Dispose()
{
Dispose(true);
}
public void SendData(byte[] data)
{
if (connectedSocket == null)
{
return;
}
connectedSocket.Send(data);
}
private void BeginReceiveAsync(Socket sock, SocketAsyncEventArgs e)
{
if (!sock.ReceiveAsync(e))
{
ReceiveCompleted(sock, e);
}
}
private void Connected(Socket socket)
{
var endPoint = (IPEndPoint)socket.RemoteEndPoint;
connectedSocket = socket;
OnSocketConnected(endPoint);
}
private void Disconnect(Socket socket)
{
var endPoint = (IPEndPoint)socket.RemoteEndPoint;
socket.Close();
connectedSocket = null;
OnSocketDisconnected(endPoint);
tcpListener.BeginAcceptSocket(EndAcceptSocket, tcpListener);
}
private void Dispose(bool disposing)
{
if (this.disposed == false)
{
if (disposing)
{
try
{
if (tcpListener != null)
{
this.disposed = true;
tcpListener.Stop();
}
}
catch (Exception ex)
{
TraceLog.Error("TcpServer: tcpListener.Stop(): {0}", ex.Message);
}
try
{
if (connectedSocket != null)
{
connectedSocket.Close();
connectedSocket = null;
}
}
catch (SocketException ex)
{
TraceLog.Error("TcpServer: connectedSocket.Close(): {0}", ex);
}
}
this.disposed = true;
}
}
private void EndAcceptSocket(IAsyncResult asyncResult)
{
var listener = (TcpListener)asyncResult.AsyncState;
if (disposed)
{
return;
}
try
{
Socket sock = listener.EndAcceptSocket(asyncResult);
Connected(sock);
var e = new SocketAsyncEventArgs();
e.Completed += ReceiveCompleted;
e.SetBuffer(new byte[SocketBufferSize], 0, SocketBufferSize);
BeginReceiveAsync(sock, e);
}
catch (SocketException ex)
{
TraceLog.Error("TcpServer.EndAcceptSocket: {0}", ex.Message);
}
catch (Exception ex)
{
TraceLog.Error("TcpServer.EndAcceptSocket: {0}", ex.Message);
}
}
private void OnDataReceived(byte[] data, IPEndPoint ipEndPoint)
{
if (DataReceived != null)
{
DataReceived(this, new DataReceivedEventArgs(data, ipEndPoint));
}
}
private void OnSocketConnected(IPEndPoint ipEndPoint)
{
if (SocketConnected != null)
{
SocketConnected(this, new IPEndPointEventArgs(ipEndPoint));
}
}
private void OnSocketDisconnected(IPEndPoint ipEndPoint)
{
if (SocketDisconnected != null)
{
SocketDisconnected(this, new IPEndPointEventArgs(ipEndPoint));
}
}
private void ReceiveCompleted(object sender, SocketAsyncEventArgs e)
{
var sock = (Socket)sender;
if (!sock.Connected)
{
Disconnect(sock);
}
try
{
int size = e.BytesTransferred;
if (size == 0)
{
Disconnect(sock);
}
else
{
var buf = new byte[size];
Array.Copy(e.Buffer, buf, size);
ReceiveData(buf, (IPEndPoint)sock.RemoteEndPoint);
BeginReceiveAsync(sock, e);
}
}
catch (SocketException ex)
{
TraceLog.Error("TcpServer: ReceiveCompleted: {0}", ex.Message);
}
catch (Exception ex)
{
TraceLog.Error("TcpServer: ReceiveCompleted: {0}", ex.Message);
}
}
private void ReceiveData(byte[] data, IPEndPoint endPoint)
{
OnDataReceived(data, endPoint);
}
#endregion Methods
}
Whenever I'm writing code that wraps around System.Net.Sockets.Socket, I find myself constantly adding try/catch clauses for SocketException and ObjectDisposedException. In most cases, ObjectDisposedException can simply be ignored, as it, in 99% of cases, indicates that the client has simply disconnected.
At least that's my impression of how the Socket API in .NET works. Try adding some exception handlers here and there, and see how it goes. In any case, your Disconnect method should not do more than something like this:
public void Disconnect()
{
try
{
connectedSocket.Shutdown(SocketShutdown.Both);
}
catch (Exception)
{
// Ignore the exception. The client probably already disconnected.
}
connectedSocket.Dispose(); // This is safe; a double dispose will simply be ignored.
}
I hope that sheds some light on the issue...

Categories

Resources