building a C# asynchronous TCP proxy server - c#

I am attempting to build a simple C# TCP proxy for my business so I can block certain websites from my employees. All is well except I am having trouble seeing what website the user is trying to visit... I can see that the user has connected to my proxy server so I know I am getting connections but the OnRecieve callback isn't even firing. Am I reading from the socket wrong?
Here is my code:
internal class AsyncState
{
public const int BufferSize = 4096;
public byte[] Buffer = new byte[AsyncState.BufferSize];
public Socket Socket;
public StringBuilder Content = new StringBuilder();
}
private void OnLoad(object sender, EventArgs e)
{
IPAddress[] addressCollection = Dns.GetHostAddresses(Dns.GetHostName());
foreach (IPAddress ipAddress in addressCollection)
{
if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
{
localEndPoint = new IPEndPoint(ipAddress, 8080);
Console.WriteLine("Local IP address found... " + localEndPoint.ToString());
break;
}
}
isListening = true;
thread = new Thread(new ThreadStart(
delegate()
{
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(localEndPoint);
serverSocket.Listen(10);
while (isListening)
{
resetEvent.Reset();
Console.WriteLine("Waiting for clients...");
serverSocket.BeginAccept(new AsyncCallback(OnAccept), serverSocket);
resetEvent.WaitOne();
}
}));
thread.Start();
}
}
private void OnAccept(IAsyncResult result)
{
resetEvent.Set();
Socket clientSocket = (result.AsyncState as Socket).EndAccept(result);
Console.WriteLine("Client has connected... " + clientSocket.RemoteEndPoint.ToString());
AsyncState state = new AsyncState();
state.Socket = clientSocket;
state.Socket.BeginReceive(state.Buffer, 0, AsyncState.BufferSize, SocketFlags.None, new AsyncCallback(OnRecieve), state);
}
private void OnRecieve(IAsyncResult result)
{
AsyncState state = result.AsyncState as AsyncState;
int totalRead = state.Socket.EndReceive(result);
if (totalRead > 0)
{
state.Content.Append(Encoding.ASCII.GetString(state.Buffer, 0, totalRead));
state.Socket.BeginReceive(state.Buffer, 0, AsyncState.BufferSize, SocketFlags.None, new AsyncCallback(OnRecieve), state);
}
else
{
if (state.Content.Length > 1)
Console.WriteLine("Message recieved from client... " + state.Content.ToString());
state.Socket.Close();
}
}

Building a well working proxy is no simple task as you will have to understand and handle HTTP etc. in both directions...
I would recommend to either use an existing library for that OR some configurable proxy...
http://www.mentalis.org/soft/projects/proxy/ (with source)
http://sourceforge.net/p/portfusion/home/PortFusion/ (with source)
http://www.wingate.com/
http://www.squid-cache.org/
REMARK:
I don't know in which jurisdiction you are but using such technology without knowledge/consent of employees can in some places be a problem...
Another point: Instead of using such methods I would tell the employee to stop abusing the internet connection of the company 1-3 times and if that doesn't work I would rather fire that person... such employees is not only abusing the internet connection of the company but in worstcase is putting the company at risk (virus/trojan etc.) and also defrauding the company (if he does this in work hours)...

Related

TCP Socket Server custom class for socket identifier in C#

I've been looking at many tcp client/server examples and would want to know how one can go about creating a method to identify each client. One way I know is through lets say, a log in authentication. I know how to connect, and query a database, but how would I lets say after successful authentication, take the username and say this username is this socket. A class example or simple method would be appreciated as an example. I want to be able to target all connected clients by their username from a database individually.
Example I'm using for server
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace MultiServer
{
class Program
{
private static readonly Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private static readonly List<Socket> clientSockets = new List<Socket>();
private const int BUFFER_SIZE = 2048;
private const int PORT = 100;
private static readonly byte[] buffer = new byte[BUFFER_SIZE];
static void Main()
{
Console.Title = "Server";
SetupServer();
Console.ReadLine(); // When we press enter close everything
CloseAllSockets();
}
private static void SetupServer()
{
Console.WriteLine("Setting up server...");
serverSocket.Bind(new IPEndPoint(IPAddress.Any, PORT));
serverSocket.Listen(0);
serverSocket.BeginAccept(AcceptCallback, null);
Console.WriteLine("Server setup complete");
}
/// <summary>
/// Close all connected client (we do not need to shutdown the server socket as its connections
/// are already closed with the clients).
/// </summary>
private static void CloseAllSockets()
{
foreach (Socket socket in clientSockets)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
serverSocket.Close();
}
private static void AcceptCallback(IAsyncResult AR)
{
Socket socket;
try
{
socket = serverSocket.EndAccept(AR);
}
catch (ObjectDisposedException) // I cannot seem to avoid this (on exit when properly closing sockets)
{
return;
}
clientSockets.Add(socket);
socket.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCallback, socket);
Console.WriteLine("Client connected, waiting for request...");
serverSocket.BeginAccept(AcceptCallback, null);
}
private static void ReceiveCallback(IAsyncResult AR)
{
Socket current = (Socket)AR.AsyncState;
int received;
try
{
received = current.EndReceive(AR);
}
catch (SocketException)
{
Console.WriteLine("Client forcefully disconnected");
// Don't shutdown because the socket may be disposed and its disconnected anyway.
current.Close();
clientSockets.Remove(current);
return;
}
byte[] recBuf = new byte[received];
Array.Copy(buffer, recBuf, received);
string text = Encoding.ASCII.GetString(recBuf);
Console.WriteLine("Received Text: " + text);
if (text.ToLower() == "get time") // Client requested time
{
Console.WriteLine("Text is a get time request");
byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
current.Send(data);
Console.WriteLine("Time sent to client");
}
else if (text.ToLower() == "exit") // Client wants to exit gracefully
{
// Always Shutdown before closing
current.Shutdown(SocketShutdown.Both);
current.Close();
clientSockets.Remove(current);
Console.WriteLine("Client disconnected");
return;
}
else
{
Console.WriteLine("Text is an invalid request");
byte[] data = Encoding.ASCII.GetBytes("Invalid request");
current.Send(data);
Console.WriteLine("Warning Sent");
}
current.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
}
}
}
There's a very simple solution to that when you're using the asynchronous callbacks (though I'd strongly recommend switching to a newer approach, or even better, an existing library - raw TCP is hard to do right).
The callback delegate can point to an instance method. This means you can have something like this:
class Client
{
private readonly Socket socket;
public readonly byte[] ReceiveBuffer = new byte[BUFFFER_SIZE];
public Client(Socket socket)
{
this.socket = socket;
}
public void ReceiveCallback(IAsyncResult AR)
{
// Handle the received data as usual
}
}
And then in your AcceptCallback method, just use a list of Client instead of Socket, and the final BeginReceive call as such:
var client = new Client(socket);
socket.BeginReceive(client.ReceiveBuffer, 0, BUFFER_SIZE, SocketFlags.None, client.ReceiveCallback,
socket);
clients.Add(newClient);
But again, writing custom networking is hard. Use an existing solution if possible - there's plenty to choose from.
Also, the ObjectDisposedExceptions you're getting are because you're doing Shutdown immediately followed by a Close. This is wrong. TCP shutdown is coöperative - you need to wait for the client socket to close before you call Close on your socket. What you're doing is rudely interrupting the connection before it has a chance to resolve itself. Again - TCP is hard to do right, you need to learn how it works very thoroughly.

Simple socket server in Unity

I want to use a C# plugin in my Unity project. That plugin should act as a server which will get values from a client so that I'd be able to use those values for further processing.
The issue is that the server has infinite loop. And infinite loops cause Unity to hang. How to handle this?
EDIT: I'm attaching a code snippet of server program. In my opinion, there are 2 points which may be causing problem. The infinite loops and the point where program is suspended as commented in code:
void networkCode()
{
// 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.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 1755);
// Create a TCP/IP 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)
{
// Program is suspended while waiting for an incoming connection.
Debug.Log("HELLO"); //It works
handler = listener.Accept();
Debug.Log("HELLO"); //It doesn't work
data = null;
// An incoming connection needs to be processed.
while (true)
{
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
if (data.IndexOf("<EOF>") > -1)
{
break;
}
System.Threading.Thread.Sleep(1);
}
System.Threading.Thread.Sleep(1);
}
}
catch (Exception e)
{
Debug.Log(e.ToString());
}
}
EDIT: After help from #Programmer, the C# plugin is complete. But Unity is not reading the correct values. I'm attaching the Unity side code:
using UnityEngine;
using System;
using SyncServerDLL; //That's our library
public class receiver : MonoBehaviour {
SynchronousSocketListener obj; //That's object to call server methods
// Use this for initialization
void Start() {
obj = new SynchronousSocketListener ();
obj.startServer ();
}
// Update is called once per frame
void Update() {
Debug.Log (obj.data);
}
}
I have tested SynchronousSocketListener class thoroughly in Visual Studio. It is giving good results there.
Use Thread to do your server Listen and read and write actions.
You can declare socket and other networkstream objects as public then initialize them in a thread function.
Unity does not work well with while loops in Threads and may freeze sometimes, but you can fix that by adding System.Threading.Thread.Sleep(1); in your while loop where you are reading or waiting for data to arrive from socket.
Make sure to stop the Thread in OnDisable() function. Do NOT access Unity API from the new Thread function. Just do only the socket stuff there and return the data to a public variable.
System.Threading.Thread SocketThread;
volatile bool keepReading = false;
// Use this for initialization
void Start()
{
Application.runInBackground = true;
startServer();
}
void startServer()
{
SocketThread = new System.Threading.Thread(networkCode);
SocketThread.IsBackground = true;
SocketThread.Start();
}
private string getIPAddress()
{
IPHostEntry host;
string localIP = "";
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
localIP = ip.ToString();
}
}
return localIP;
}
Socket listener;
Socket handler;
void networkCode()
{
string data;
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// host running the application.
Debug.Log("Ip " + getIPAddress().ToString());
IPAddress[] ipArray = Dns.GetHostAddresses(getIPAddress());
IPEndPoint localEndPoint = new IPEndPoint(ipArray[0], 1755);
// Create a TCP/IP socket.
listener = new Socket(ipArray[0].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)
{
keepReading = true;
// Program is suspended while waiting for an incoming connection.
Debug.Log("Waiting for Connection"); //It works
handler = listener.Accept();
Debug.Log("Client Connected"); //It doesn't work
data = null;
// An incoming connection needs to be processed.
while (keepReading)
{
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
Debug.Log("Received from Server");
if (bytesRec <= 0)
{
keepReading = false;
handler.Disconnect(true);
break;
}
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
if (data.IndexOf("<EOF>") > -1)
{
break;
}
System.Threading.Thread.Sleep(1);
}
System.Threading.Thread.Sleep(1);
}
}
catch (Exception e)
{
Debug.Log(e.ToString());
}
}
void stopServer()
{
keepReading = false;
//stop thread
if (SocketThread != null)
{
SocketThread.Abort();
}
if (handler != null && handler.Connected)
{
handler.Disconnect(false);
Debug.Log("Disconnected!");
}
}
void OnDisable()
{
stopServer();
}

C# UdpClient.Receive() not working with multicast no matter what I do

tried to solve this alone for the past I don't even know but no googling will help me here, I would need some advice with this one. I am receiving UDP packets from another PC on my local network every 10 seconds, can see them in wireshark but the application is stuck on the udpClient.Receive() line. The multicast group and port are the right values, checked in main() n+1 times. Please suggest a solution if you have any idea that might help. Thanks.
(I'm trying to receive the server's information so that th application can automaticaly start to communicate vith it via TCP)
class MulticastListener {
private UdpClient udpClient;
private IPEndPoint remoteEndPoint;
IPAddress multicastIP;
private int port;
public MulticastListener(ref IPAddress multicastIP, int port) {
remoteEndPoint = new IPEndPoint(IPAddress.Any, port);
this.multicastIP = multicastIP;
this.port = port;
udpClient = new UdpClient();
udpClient.Client.Bind(remoteEndPoint);
}
public IPEndPoint GetServer() {
try {
udpClient.JoinMulticastGroup(multicastIP);
} catch (ObjectDisposedException e) {
Console.WriteLine("ERROR: The underlying socket has been closed!");
} catch (SocketException e) {
Console.WriteLine("ERROR: An error occurred when accessing the socket!");
} catch (ArgumentException e) {
Console.WriteLine("ERROR: The IP address is not compatible with the AddressFamily value that defines the addressing scheme of the socket!");
}
Byte[] serverInfoBytes = udpClient.Receive(ref remoteEndPoint);
Stream stream = new MemoryStream(serverInfoBytes); //receives a serialised IPEndpoint object
BinaryFormatter formatter = new BinaryFormatter();
udpClient.Close();
return (IPEndPoint)formatter.Deserialize(stream);
}
}
As I commented, your code works fine for me 100% as is. I would check you are sending on the same subnet you are receiving on. Perhaps your sender is not configured to the right interface?
Perhaps it would help to try out a different sender, here is what I used to test:
static void Main(string[] args)
{
//Configuration
var interfaceIp = IPAddress.Parse("192.168.9.121");
var interfaceEndPoint = new IPEndPoint(interfaceIp, 60001);
var multicastIp = IPAddress.Parse("230.230.230.230");
var multicastEndPoint = new IPEndPoint(multicastIp, 60001);
//initialize the socket
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.ExclusiveAddressUse = false;
socket.MulticastLoopback = false;
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
MulticastOption option = new MulticastOption(multicastEndPoint.Address, interfaceIp);
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, option);
//bind on a network interface
socket.Bind(interfaceEndPoint);
//initialize args for sending packet on the multicast channel
var sockArgs = new SocketAsyncEventArgs();
sockArgs.RemoteEndPoint = multicastEndPoint;
sockArgs.SetBuffer(new byte[1234], 0, 1234);
//send an empty packet of size 1234 every 3 seconds
while (true)
{
socket.SendToAsync(sockArgs);
Thread.Sleep(3000);
}
}

C# UDP Server/Client - NAT

Iam trying to send a message (via UDP) from my client to my server. The server should answer this message and if the client receives this answer he should print out a message.
If i run the client and server on my local network everything works fine.
If i try to connect through the internet from another PC outside my network the server receives the request of the client, sends an answer back, but the client never receives this answer. The client and the server are both behind a NAT but i portforwarded the ports at the server´s NAT and the server got its own DNS. I already tried NAT traversal but it gives me the same IP and port adress as the IPEndPoint of the server, after receiveing the request of the client, does.
I´ve got no idea how to fix this, so any guidance would be much appreciated.
Client
public static void Main()
{
Thread receiveThread = new Thread(new ThreadStart(ReceiveData));
receiveThread.Start();
object[] oData = {1};
sendData(oData, 0,0, "Li");
while (true)
{
Console.ReadLine();
}
}
private void receiveData()
{
string receivePort = 8080;
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.ReceiveTimeout = 1000;
IPEndPoint end = new IPEndPoint(IPAddress.Any, receivePort);
client.Bind(end);
while (true)
{
try
{
byte[] data = new byte[1024];
client.Receive(data, 0, data.Length, SocketFlags.None);
object[] receivedObj = Deserialize(data);
string sType = (string)receivedObj[3];
if (sType == "Li")
{
console.WriteLine("received Li");
}
}
catch (Exception err)
{
Console.WriteLine(err.ToString());
}
}
}
public static void sendData(object[] oData, int iFrom, int iTo, string sType)
{
string sendPort = 17171;
UdpClient client = new UdpClient();
string IP = "ThisIsTheDNSofmyServer.com"; //ServerDNS
//string IP = "192.168.xxx.xxx"; //serverIP in LAN
if (IP.StartsWith("T"))
{
IP = (Dns.GetHostAddresses(IP))[0].ToString();
}
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP), sendPort);
oData[1] = iFrom;
oData[2] = iTo;
oData[3] = sType;
Byte[] data = Serialize(oData);
client.Send(data, data.Length, remoteEndPoint);
}
The server´s code is almost the same:
public static void Main()
{
Thread receiveThread = new Thread(new ThreadStart(ReceiveData));
receiveThread.Start();
while (true)
{
Console.ReadLine();
}
}
private static void ReceiveData()
{
int receivePort = 17171;
UdpClient client = new UdpClient(receivePort);
while (true)
{
try
{
IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
byte[] data = new byte[1024];
data = client.Receive(ref anyIP);
object[] receivedObj = Deserialize(data);
//if I receive data send an Answer
sendData(receivedObj, 0,0,"Li",anyIP.Address.ToString());
}
catch (Exception err)
{
Console.WriteLine(err.ToString());
}
}
}
private static void sendData(object[] oData, int iFrom, int iTo, string sType, string IP)
{
int sendPort = 8080;
object[] paket = { oData, iFrom, iTo, sType };
UdpClient client = new UdpClient();
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP), sendPort);
client.Send(data, data.Length, remoteEndPoint);
}
i believe this is a port cofniguration issue,
8080 is almost likely to be configured as alternate http
"The UdpClient you use to receive datagrams must be created using the multicast port number" from MSDN
Hope this helps and good luck
Krishna
You do not need to do anything unordinary to traverse NAT in the setup you described, you just need to send it from the server back to your client; specifically: you must send back to the end point, i.e. IP and port, you received it on.
client.Send(data, data.Length, remoteEndPoint); // remoteEndPoint is the IPEndPoint you got the datagram on

Stopping an asynchronous TCP server on separate thread in C#

I have implemented an asynchronous TCP server that is spawned by another process. It starts fine and operates as expected, however I am having trouble terminating the server when I end the process that started it.
The following is my current TCP server and stopping function from the other process.
TCP Server
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 : Strategy
{
//Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public volatile bool listening = true;
//User-specified port number.
private int Port;
public AsynchronousSocketListener(int port)
{
Port = port;
}
public void StopListening()
{
listening = false;
}
public void StartListening()
{
//Data buffer for incoming data.
byte[] bytes = new Byte[1024];
//Establish the local endpoint for the socket.
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, Port);
//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 (listening)
{
//Set the event to nonsignaled state.
allDone.Reset();
//Start an asychronous socket to listen for connections.
Print("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
//Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Print(e.ToString());
}
}
public void AcceptCallback(IAsyncResult arg)
{
//Signal the main thread to continue.
allDone.Set();
//Get the socket that handles the client request.
Socket listener = (Socket) arg.AsyncState;
Socket handler = listener.EndAccept(arg);
//Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
public void ReadCallback(IAsyncResult arg)
{
String content = String.Empty;
//Retrieve the state object and the handler socket
//from the asynchronous state object.
StateObject state = (StateObject) arg.AsyncState;
Socket handler = state.workSocket;
//Read data from the client socket.
int bytesRead = handler.EndReceive(arg);
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.
Print("Read " + content.Length + " bytes from socket. \n Data : " + 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 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 void SendCallback(IAsyncResult arg)
{
try
{
//Retrieve the socket from the state object.
Socket handler = (Socket) arg.AsyncState;
//Complete sending the data to the remote device.
int bytesSent = handler.EndSend(arg);
Print("Sent " + bytesSent + " bytes to client.");
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (Exception e)
{
Print(e.ToString());
}
}
}
Spawning process
//private NinjaTerminal.Server server;
private NinjaTerminal.AsynchronousSocketListener server;
private Thread listenThread;
private int _Port = 8080;
protected override void OnStartUp()
{
server = new NinjaTerminal.AsynchronousSocketListener(Port);
listenThread = new Thread(new ThreadStart(server.StartListening));
listenThread.Start();
}
protected override void OnTermination()
{
listenThread.stopListening();
listenThread.Join();
}
Now I've verified that OnTermination() gets called, and it does join to the server thread, however the server thread never ends.
I would love some insights as to why, and suggestions to a better architecture or more than welcome. At this stage I haven't invested much into anything but setting up the TCP server, so if you have a different/better idea I'd love to hear it.
Also, I've searched high and low through StackOverflow for an answer already and none of them really applied to an asynchronous TCP server. And I'm using .NET 3.5
Code addition to Reed's answer
public void StopListening()
{
listening = false;
allDone.Set();
}
public void StartListening()
{
//Data buffer for incoming data.
byte[] bytes = new Byte[1024];
//Establish the local endpoint for the socket.
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, Port);
//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 (listening)
{
//Set the event to nonsignaled state.
allDone.Reset();
//Start an asychronous socket to listen for connections.
Print("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
//Wait until a connection is made before continuing.
allDone.WaitOne();
}
listener.Close();
}
catch (Exception e)
{
Print(e.ToString());
}
}
You need to change StopListening to also include a call to signal your WaitHandle:
public void StopListening()
{
this.listening = false;
this.allDone.Set();
}
Without this, your StartListening routine will hang forever here:
//Wait until a connection is made before continuing.
allDone.WaitOne();

Categories