I used to write socket programs in C and can't understand why the above is happening.
My server blocks at a Receive call, when it returns 0, I break out of the while loop and shutdown the thread.
public class MyServer {
public MyServer() {
}
public void Init() {
ThreadPool.QueueUserWorkItem(StartListening);
while (true) {
Console.Read();
}
}
public void StartListening(Object state) {
// Establish the local endpoint for the socket.
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try {
// Bind the socket to the local endpoint and listen for incoming connections.
listener.Bind(localEndPoint);
listener.Listen(100);
while (true) {
Console.WriteLine("Waiting for a connection...");
// get connection
Socket client = listener.Accept();
// push client to another thread
ThreadPool.QueueUserWorkItem(HandleClient, client);
}
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
private void HandleClient(Object obj) {
// Get the socket that handles the client request.
Socket client = (Socket)obj;
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
try {
while (true) {
int bytesRead = client.Receive(state.buffer);
Console.WriteLine("bytesRead=" + bytesRead);
// remote dc.
if (bytesRead == 0)
break;
String content = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content);
client.Send(state.buffer, 0, state.buffer.Length, 0);
}
} catch (SocketException e) {
Console.WriteLine("SocketException : {0}", e.ToString());
}
client.Shutdown(SocketShutdown.Both);
client.Close();
}
private void Send(Socket handler, String data) {
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
//handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
}
However, when I click on the close button ("x") of the client, server's Receive call throws a SocketException. According to MSDN's Remarks section, this shouldn't happen because I've satisfied both the connection-oriented part (see above) and client shutdown part(see below) conditions.
Client.cs (pseudo):
public class MyClient {
public void Init() {
byte[] bytes = new byte[1024];
Socket sender = null;
try {
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint remoteEP = new IPEndPoint(ipAddress, 11000);
sender = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
sender.Connect(remoteEP);
Console.WriteLine("Socket connected to {0}",
sender.RemoteEndPoint.ToString());
while (true) {
// Encode the data string into a byte array.
String input = Console.ReadLine();
byte[] msg = Encoding.ASCII.GetBytes(input);
// Send the data through the socket.
int bytesSent = sender.Send(msg);
// Receive the response from the remote device.
int bytesRec = sender.Receive(bytes);
Console.WriteLine("Echoed test = {0}",
Encoding.ASCII.GetString(bytes, 0, bytesRec));
}
} catch (ArgumentNullException ane) {
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
} catch (SocketException se) {
Console.WriteLine("SocketException : {0}", se.ToString());
} catch (Exception e) {
Console.WriteLine("Unexpected exception : {0}", e.ToString());
} finally {
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
}
}
My shallow understanding of finally blocks is that it will always execute. But it doesn't seem to be the case here.
SO, what did I do wrong here? Should I just catch the exception, close the client socket on the server side and just move on, ignoring it? But I would prefer if an exception were not thrown at all.
Related
I'm using c# sockets to create a client-server connection on my pc, for now locally, but the exception in the title is the only signal I receive back.
I've already tried disabling the firewall, checking if the port I'm using(51111) is listening(yes) and unticking everything in LAN settings(to avoid proxying), all of them at the same time too.
My code(just temporary test code)
Server Class
class Server
{
private Socket listener;
public void SocketServer()
{
int maxBuffer = 1024;
Console.WriteLine("LISTENER ENABLED");
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Any, 51111));
listener.Listen(5);
while (true)
{
Console.WriteLine("WAITING FOR CONNECTION");
Socket socket = listener.Accept();
string receivedMessage = string.Empty;
while (true)
{
byte[] receivedBytes = new byte[maxBuffer];
int bytesReceivedCount = socket.Receive(receivedBytes);
receivedMessage += Encoding.ASCII.GetString(receivedBytes, 0, bytesReceivedCount);
if (receivedMessage.IndexOf('\n') > -1)
{
break;
}
}
Console.WriteLine("Message from Client : " + receivedMessage);
string reply = ("Message received!");
byte[] replyBytes = Encoding.ASCII.GetBytes(reply);
socket.Send(replyBytes);
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}
Client Class
class Client
{
public void SocketClient(string request)
{
int maxBuffer = 1024;
try
{
IPHostEntry iPHostEntry = Dns.GetHostEntry(Dns.GetHostName());
IPAddress address = iPHostEntry.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(address, 51111);
Socket sender = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
sender.Connect(remoteEP);
Console.WriteLine("Connected to " + sender.RemoteEndPoint.ToString());
byte[] message = Encoding.ASCII.GetBytes(request);
int bytesSent = sender.Send(message);
byte[] response = new byte[maxBuffer];
int bytesReceived = sender.Receive(response);
Console.WriteLine("Received : " + Encoding.ASCII.GetString(response, 0, bytesReceived));
}
catch (ArgumentNullException ane)
{
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
}
catch (SocketException se)
{
Console.WriteLine("SocketException : {0}", se.ToString());
}
catch (Exception e)
{
Console.WriteLine("Unexpected exception : {0}", e.ToString());
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
Thank you
I have built a server and client which communicate via sockets.
When i run both the server and the client on the same machine both the server and the client receive the messages which are expected.
when i run the server on a VM or a different physical machine and the client on my main machine the server receives messages fine, but the client never receives the reply's
I have made sure to dissable windows firewall and my anti virus on all 3 machines (the 2 physical and one virtual one) to ensure its not a security issue.
The relevant code is as follows
SERVER
public class SynchronousSocketListener
{
// Incoming data from the client.
public static string data = null;
public void StartListening()
{
InstructionProcessor instructionProcessor = new InstructionProcessor();
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// Dns.GetHostName returns the name of the
// host running the application.
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
// Create a TCP/IP socket.
Socket listener = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and
// listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
// Start listening for connections.
while (true)
{
Console.WriteLine("Waiting for a connection...");
// Program is suspended while waiting for an incoming connection.
Socket handler = listener.Accept();
data = null;
// An incoming connection needs to be processed.
while (true)
{
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
if (data.IndexOf("<EOF>") > -1)
{
break;
}
}
data = data.Substring(0, data.Length - 5);
// Show the data on the console.
string response = instructionProcessor.doSomething(data);
// Echo the data back to the client.
byte[] msg = Encoding.ASCII.GetBytes(response);
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
}
CLIENT
public static string StartClient(string message, string ip)
{
// Data buffer for incoming data.
byte[] bytes = new byte[1024];
//Declare this at class scope level so it can be returned outside of try/catch blocks
string response = null;
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
// This example uses port 11000 on the local computer.
IPHostEntry ipHostInfo = Dns.GetHostEntry(ip);
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, 11000);
//string hostName = Dns.GetHostName();
//string myIP = Dns.GetHostByName(hostName).AddressList[0].ToString(); ;
//Debug.WriteLine( ipAddress );
// Create a TCP/IP socket.
Socket sender = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
// Connect the socket to the remote endpoint. Catch any errors.
try
{
sender.Connect(remoteEP);
Console.WriteLine("Socket connected to {0}",
sender.RemoteEndPoint.ToString());
// Encode the data string into a byte array.
byte[] msg = Encoding.ASCII.GetBytes(message + "<EOF>");
// Send the data through the socket.
int bytesSent = sender.Send(msg);
// Receive the response from the remote device.
int bytesRec = sender.Receive(bytes);
Console.WriteLine("Echoed test = {0}",
Encoding.ASCII.GetString(bytes, 0, bytesRec));
response = Encoding.ASCII.GetString(bytes, 0, bytesRec);
// Release the socket.
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
catch (ArgumentNullException ane)
{
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
}
catch (SocketException se)
{
Console.WriteLine("SocketException : {0}", se.ToString());
}
catch (Exception e)
{
Console.WriteLine("Unexpected exception : {0}", e.ToString());
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
return response;
}
}
Maybe because client is receiving more than 1024 byte. Try to increase the size of the received buffer.
Also add if (data.IndexOf("") > -1) into the client project.
The code below creates socket server and client
I start the server and if I start one after the other the clients it works fine
If I start three clients immediately, then for one or more clients the BeginAccept event is not fired
The results bellow are after executing the code bellow
Server Started
Server is waiting for a connection...
Client 0.0.0.0:6352 requests connection
Client 0.0.0.0:6353 requests connection
Client 127.0.0.1:6351 requests connection
Client 127.0.0.1:6351 connected
Client 127.0.0.1:6352 connected
Client 127.0.0.1:6353 connected
ServerOnClientConnection Client: 127.0.0.1:6351
Server is waiting for a connection...
ServerOnClientConnection Client: 127.0.0.1:6353
code follows
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace Test {
public class TestSockets {
#region server
Socket serverSocket;
bool serverIsAlive;
public ManualResetEvent waitForConnection = new ManualResetEvent(false);
private Encoding encod = Encoding.Unicode;
public void ServerStartInThread() {
byte[] bytes = new Byte[1024];
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 5500);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket = socket;
try {
socket.Bind(localEndPoint);
socket.Listen(100);
Thread pollThread = new Thread(delegate () {
serverIsAlive = true; // needs if reopen
SendMessage("Server Started");
while (serverIsAlive) {
try {
SendMessage("Server is waiting for a connection...");
socket.BeginAccept(new AsyncCallback(ServerOnClientConnection), socket);
waitForConnection.Reset();
waitForConnection.WaitOne();
}
catch (Exception ex) {
SendMessage("Server: " + ex.ToString());
}
}
SendMessage("Server Stopped");
socket.Close();
}) {
Name = "SocketServer"
};
pollThread.Start();
}
catch (Exception ex) {
SendMessage("Server: " + ex.ToString());
}
}
public void ServerOnClientConnection(IAsyncResult ar) {
try {
Socket listener = (Socket)ar.AsyncState;
Socket clientSocket = listener.EndAccept(ar);
SendMessage("ServerOnClientConnection Client: " + clientSocket.RemoteEndPoint.ToString());
StateObject state = new StateObject() {
socket = clientSocket
};
clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ServerReceiveCallback), state);
waitForConnection.Set();
}
catch (Exception ex) {
SendMessage("ServerOnClientConnection: " + ex.ToString());
}
}
public void ServerReceiveCallback(IAsyncResult ar) {
StateObject state = (StateObject)ar.AsyncState;
Socket socket = state.socket;
try {
if (socket == null) return;
if (!socket.Connected) {
return;
}
int bytesRead = socket.EndReceive(ar);
if (bytesRead > 0) {
state.sb.Append(encod.GetString(state.buffer, 0, bytesRead));
socket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ServerReceiveCallback), state);
}
}
catch (Exception ex) {
SendMessage("ServerReceiveCallback: " + ex.ToString());
}
}
#endregion
#region client
private Socket client;
private bool isAlive = false;
private ManualResetEvent connectDone = new ManualResetEvent(false);
public void StartInThread() {
try {
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint remoteEP = new IPEndPoint(ipAddress, 5500);
Thread pollThread = new Thread(delegate () {
isAlive = true;
while (isAlive) {
try {
if (client != null && client.Connected) {
continue;
}
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.BeginConnect(remoteEP, new AsyncCallback(ClientConnectCallback), client);
SendMessage(string.Format("Client {0} requests connection", client.LocalEndPoint.ToString()));
connectDone.Reset();
connectDone.WaitOne(3000, false);
if (client.Connected) {
StateObject state = new StateObject() {
socket = client
};
SendMessage(string.Format("Client {0} connected", client.LocalEndPoint.ToString()));
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ClientReceiveCallback), state);
}
}
catch (Exception ex) {
SendMessage("ClientStartInThread1: " + ex.ToString());
}
}
SendMessage("Client Disconnected");
}) {
Name = "ClientThread"
};
pollThread.Start();
}
catch (Exception ex) {
SendMessage("ClientStartInThread2: " + ex.ToString());
}
}
private void ClientConnectCallback(IAsyncResult ar) {
try {
Socket socket = (Socket)ar.AsyncState;
socket.EndConnect(ar);
connectDone.Set();
}
catch (Exception ex) {
SendMessage("ClientConnectCallback: " + ex.ToString());
}
}
private void ClientReceiveCallback(IAsyncResult ar) {
StateObject state = (StateObject)ar.AsyncState;
Socket socket = state.socket;
if (socket == null || !socket.Connected) return;
try {
int bytesRead = socket.EndReceive(ar);
if (bytesRead > 0) {
state.sb.Append(encod.GetString(state.buffer, 0, bytesRead));
socket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ClientReceiveCallback), state);
}
else {
socket.Close();
}
}
catch (Exception ex) {
SendMessage("ClientReceiveCallback: " + ex.ToString());
socket.Close();
}
}
#endregion
private void SendMessage(string v) {
System.Diagnostics.Debug.WriteLine(v);
}
public static void Start() {
TestSockets server = new TestSockets();
server.ServerStartInThread();
TestSockets c1 = new TestSockets();
c1.StartInThread();
TestSockets c2 = new TestSockets();
c2.StartInThread();
TestSockets c3 = new TestSockets();
c3.StartInThread();
}
}
public class StateObject {
public Socket socket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}
}
You have a race condition in your code that results in the waitForConnection event handle being set twice, with the second call to Set() having no effect, before the main server thread has a chance to proceed past the BeginAccept() and reset the handle. This causes it to miss the second set.
One way to fix it would be to switch to a semaphore object. For example:
#region server
Socket serverSocket;
bool serverIsAlive;
SemaphoreSlim waitForConnection = new SemaphoreSlim(0);
private Encoding encod = Encoding.Unicode;
public void ServerStartInThread()
{
byte[] bytes = new Byte[1024];
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 5500);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket = socket;
try
{
socket.Bind(localEndPoint);
socket.Listen(100);
Thread pollThread = new Thread(delegate () {
serverIsAlive = true; // needs if reopen
SendMessage("Server Started");
while (serverIsAlive)
{
try
{
SendMessage("Server is waiting for a connection...");
socket.BeginAccept(new AsyncCallback(ServerOnClientConnection), socket);
waitForConnection.Wait();
}
catch (Exception ex)
{
SendMessage("Server: " + ex.ToString());
}
}
SendMessage("Server Stopped");
socket.Close();
})
{
Name = "SocketServer"
};
pollThread.Start();
}
catch (Exception ex)
{
SendMessage("Server: " + ex.ToString());
}
}
public void ServerOnClientConnection(IAsyncResult ar)
{
try
{
Socket listener = (Socket)ar.AsyncState;
Socket clientSocket = listener.EndAccept(ar);
SendMessage("ServerOnClientConnection Client: " + clientSocket.RemoteEndPoint.ToString());
StateObject state = new StateObject()
{
socket = clientSocket
};
clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ServerReceiveCallback), state);
waitForConnection.Release();
}
catch (Exception ex)
{
SendMessage("ServerOnClientConnection: " + ex.ToString());
}
}
This will allow the ServerOnClientConnection() method to increment the semaphore count, so that the main server thread can continue to loop until all of the accepted connections have been observed.
However, frankly, the MSDN examples that use these event handles (which is what I'm assuming your code is based on, either directly or indirectly) are IMHO simply broken. They introduce thread synchronization complexities where none is actually needed, unnecessarily complicating the code and making it harder to get the code to work correctly.
A more idiomatic approach would be to not have the extra thread at all, call BeginAccept() once in the ServerStartInThread() method (which you'd probably rename to just ServerStart()) and call BeginAccept() in the ServerOnClientConnection() method after handling the currently accepted client. I.e. just like you handle the BeginReceive() now.
That said, IMHO even the idiomatic approach is outdated. It worked very well when the API was first designed, but .NET has come a long way since then and has much better mechanisms for dealing with asynchronous operations like this. I posted in this answer an example of a simple chat server that shows how you can use async/await to implement this sort of thing in a much simpler, easier-to-read way. You may want to look at that for ideas on how to apply the same techniques to your own code.
I just copied the code from msdn examples, asynchronous server and client socket program. But I am getting error System.Net.SocketsException: No connection could be made because the target machine actively refused it 127.0.0.1:11000
Client Program :
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
// State object for receiving data from remote device.
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousClient
{
// The port number for the remote device.
private const int port = 11000;
// ManualResetEvent instances signal completion.
private static ManualResetEvent connectDone =
new ManualResetEvent(false);
private static ManualResetEvent sendDone =
new ManualResetEvent(false);
private static ManualResetEvent receiveDone =
new ManualResetEvent(false);
// The response from the remote device.
private static String response = String.Empty;
private static void StartClient()
{
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
// The name of the
// remote device is "host.contoso.com".
IPHostEntry ipHostInfo = Dns.Resolve("localhost");
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
// Send test data to the remote device.
Send(client, "This is a test<EOF>");
sendDone.WaitOne();
// Receive the response from the remote device.
Receive(client);
receiveDone.WaitOne();
// Write the response to the console.
Console.WriteLine("Response received : {0}", response);
// Release the socket.
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}",
client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
// All the data has arrived; put it in response.
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
// Signal that all bytes have been received.
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Send(Socket client, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args)
{
StartClient();
return 0;
}
}
Server Program :
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
// State object for reading client data asynchronously
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousSocketListener
{
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public AsynchronousSocketListener()
{
}
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer, 0, bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1)
{
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content);
// Echo the data back to the client.
Send(handler, content);
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args)
{
StartListening();
return 0;
}
}
change
IPAddress ipAddress = ipHostInfo.AddressList[0];
to
IPAddress ipAddress = IPAddress.Any;
in StartListening method....
public static byte[] StartClient(string ip, int port, byte[] message, bool needBack, out string errorMsg)
{
// Data buffer for incoming data.
byte[] bytes = new byte[1024];
// Connect to a remote device.
try
{
// Establish the remote endpoint for the socket.
IPAddress ipAddress = IPAddress.Parse(ip);
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
Socket sender = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Connect the socket to the remote endpoint. Catch any errors.
try
{
sender.Connect(remoteEP);
// Send the data through the socket.
int bytesSent = sender.Send(message);
if (needBack)
{
// Receive the response from the remote device.
int bytesRec = sender.Receive(bytes);
byte[] array = new byte[bytesRec];
Array.Copy(bytes, array, bytesRec);
sender.Shutdown(SocketShutdown.Both);
sender.Close();
errorMsg = "";
return array;
}
else
{
errorMsg = "";
return null;
}
}
catch (ArgumentNullException ane)
{
errorMsg = string.Format("ArgumentNullException : {0}", ane.ToString());
return null;
}
catch (SocketException se)
{
errorMsg = string.Format("SocketException : {0}", se.ToString());
return null;
}
catch (Exception e)
{
errorMsg = string.Format("Unexpected exception : {0}", e.ToString());
return null;
}
}
catch (Exception e)
{
errorMsg = string.Format("Unexpected exception : {0}", e.ToString());
return null;
}
}
I use the code above to send and receive tcp message from the server.but I read nothing.
I don't want a async method.I have searched some example codes, they are written like this. Is there something wrong that I didn't realized.Thanks for help.
public class MyTcpClient
{
IPEndPoint _remote;
Socket _socket;
public bool IsStopReceive{set;get;}
public MyTcpClient(string ip, int port)
{
IPAddress ipAddress = IPAddress.Parse(ip);
_remote = new IPEndPoint(ipAddress, port);
_socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
_socket.Connect(_remote);
ThreadPool.QueueUserWorkItem(obj=>{
IsStopReceive = false;
ReceiveMsg();
});
}
public void Send(byte[] bytes) {
_socket.Send(bytes);
}
private MemoryStream memoryResult;
private void ReceiveMsg()
{
MemoryStream memStream = new MemoryStream();
while (!IsStopReceive)
{
byte[] bytes=new byte[1024];
int result = _socket.Receive(bytes);
if (result > 0) {
memStream.Write(bytes, 0, result);
}
else if (result == 0) {
IsStopReceive = true;
break;
}
}
if (OnMsgReceive != null) {
OnMsgReceive(memStream.GetBuffer());
}
}
public Action<byte[]> OnMsgReceive{set;get;}
}
the code above can receive the data.when I create a MyTcpClient instance,it will open a thread to receive data after connect to the target.
I use a Action to get the data after it finished.but this is async.Most important is that I don't know why I missed the data with the prev method.