Asynchronous server socket using C#
来源:互联网 发布:网络剧最好的我们 编辑:程序博客网 时间:2024/05/22 16:58
/**//// <summary>
/// Author: Asad Aziz
/// Description: State object for reading client data asynchronously.
/// </summary>
public class StateObject
...{
public bool connected = false; // ID received flag
public Socket workSocket = null; // Client socket.
public Socket partnerSocket = null; // Partner socket.
public const int BufferSize = 1024; // Size of receive buffer.
public byte[] buffer = new byte[BufferSize];// Receive buffer.
public StringBuilder sb = new StringBuilder();//Received data String.
public string id = String.Empty; // Host or conversation ID
public DateTime TimeStamp;
}
/**////<summary>
/// Author: Asad Aziz
/// Description: Server is the class to control sockets
///</summary>
public class Server
...{
protected int portNumber;
protected int maxSockets;
protected int sockCount = 0;
private int convID = 0;
private Timer lostTimer;
private const int numThreads = 1;
private const int timerTimeout = 300000;
private const int timeoutMinutes = 3;
private bool ShuttingDown = false;
protected string title;
protected Hashtable connectedHT = new Hashtable();
protected ArrayList connectedSocks;
//Thread signal.
private ManualResetEvent allDone = new ManualResetEvent(false);
private Thread[] serverThread = new Thread[numThreads];
private AutoResetEvent[] threadEnd = new AutoResetEvent[numThreads];
public Server(int port, string title, string attr)
...{
this.portNumber = port;
this.title = title;
this.maxSockets =10000;
connectedSocks = new ArrayList(this.maxSockets);
}
/**//// <summary>
/// Description: Start the threads to listen to the port and process
/// messages.
/// </summary>
public void Start()
...{
// Clear the thread end events
for (int lcv = 0; lcv < numThreads; lcv++)
threadEnd[lcv] = new AutoResetEvent(false);
ThreadStart threadStart1 = new ThreadStart(StartListening);
serverThread[0] = new Thread(threadStart1);
serverThread[0].IsBackground = true;
serverThread[0].Start();
// Create the delegate that invokes methods for the timer.
TimerCallback timerDelegate = new TimerCallback(this.CheckSockets);
//Create a timer that waits one minute, then invokes every 5 minutes.
lostTimer = new Timer(timerDelegate, null, Server.timerTimeout, Server.timerTimeout);
}
/**//// <summary>
/// Description: Check for dormant sockets and close them.
/// </summary>
/// <param name="eventState">Required parameter for a timer call back
/// method.</param>
private void CheckSockets(object eventState)
...{
lostTimer.Change(System.Threading.Timeout.Infinite,
System.Threading.Timeout.Infinite);
try
...{
foreach (StateObject state in connectedSocks)
...{
if (state.workSocket == null)
...{ // Remove invalid state object
Monitor.Enter(connectedSocks);
if (connectedSocks.Contains(state))
...{
connectedSocks.Remove(state);
Interlocked.Decrement(ref sockCount);
}
Monitor.Exit(connectedSocks);
}
else
...{
if (DateTime.Now.AddTicks(-state.TimeStamp.Ticks).Minute > timeoutMinutes)
...{
RemoveSocket(state);
}
}
}
}
catch (Exception)
...{
}
finally
...{
lostTimer.Change(Server.timerTimeout, Server.timerTimeout);
}
}
/**//// <summary>
/// Decription: Stop the threads for the port listener.
/// </summary>
public void Stop()
...{
int lcv;
lostTimer.Dispose();
lostTimer = null;
for (lcv = 0; lcv < numThreads; lcv++)
...{
if (!serverThread[lcv].IsAlive)
threadEnd[lcv].Set(); // Set event if thread is already dead
}
ShuttingDown = true;
// Create a connection to the port to unblock the listener thread
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, this.portNumber);
sock.Connect(endPoint);
//sock.Close();
sock = null;
// Check thread end events and wait for up to 5 seconds.
for (lcv = 0; lcv < numThreads; lcv++)
threadEnd[lcv].WaitOne(5000, false);
}
/// Author: Asad Aziz
/// Description: State object for reading client data asynchronously.
/// </summary>
public class StateObject
...{
public bool connected = false; // ID received flag
public Socket workSocket = null; // Client socket.
public Socket partnerSocket = null; // Partner socket.
public const int BufferSize = 1024; // Size of receive buffer.
public byte[] buffer = new byte[BufferSize];// Receive buffer.
public StringBuilder sb = new StringBuilder();//Received data String.
public string id = String.Empty; // Host or conversation ID
public DateTime TimeStamp;
}
/**////<summary>
/// Author: Asad Aziz
/// Description: Server is the class to control sockets
///</summary>
public class Server
...{
protected int portNumber;
protected int maxSockets;
protected int sockCount = 0;
private int convID = 0;
private Timer lostTimer;
private const int numThreads = 1;
private const int timerTimeout = 300000;
private const int timeoutMinutes = 3;
private bool ShuttingDown = false;
protected string title;
protected Hashtable connectedHT = new Hashtable();
protected ArrayList connectedSocks;
//Thread signal.
private ManualResetEvent allDone = new ManualResetEvent(false);
private Thread[] serverThread = new Thread[numThreads];
private AutoResetEvent[] threadEnd = new AutoResetEvent[numThreads];
public Server(int port, string title, string attr)
...{
this.portNumber = port;
this.title = title;
this.maxSockets =10000;
connectedSocks = new ArrayList(this.maxSockets);
}
/**//// <summary>
/// Description: Start the threads to listen to the port and process
/// messages.
/// </summary>
public void Start()
...{
// Clear the thread end events
for (int lcv = 0; lcv < numThreads; lcv++)
threadEnd[lcv] = new AutoResetEvent(false);
ThreadStart threadStart1 = new ThreadStart(StartListening);
serverThread[0] = new Thread(threadStart1);
serverThread[0].IsBackground = true;
serverThread[0].Start();
// Create the delegate that invokes methods for the timer.
TimerCallback timerDelegate = new TimerCallback(this.CheckSockets);
//Create a timer that waits one minute, then invokes every 5 minutes.
lostTimer = new Timer(timerDelegate, null, Server.timerTimeout, Server.timerTimeout);
}
/**//// <summary>
/// Description: Check for dormant sockets and close them.
/// </summary>
/// <param name="eventState">Required parameter for a timer call back
/// method.</param>
private void CheckSockets(object eventState)
...{
lostTimer.Change(System.Threading.Timeout.Infinite,
System.Threading.Timeout.Infinite);
try
...{
foreach (StateObject state in connectedSocks)
...{
if (state.workSocket == null)
...{ // Remove invalid state object
Monitor.Enter(connectedSocks);
if (connectedSocks.Contains(state))
...{
connectedSocks.Remove(state);
Interlocked.Decrement(ref sockCount);
}
Monitor.Exit(connectedSocks);
}
else
...{
if (DateTime.Now.AddTicks(-state.TimeStamp.Ticks).Minute > timeoutMinutes)
...{
RemoveSocket(state);
}
}
}
}
catch (Exception)
...{
}
finally
...{
lostTimer.Change(Server.timerTimeout, Server.timerTimeout);
}
}
/**//// <summary>
/// Decription: Stop the threads for the port listener.
/// </summary>
public void Stop()
...{
int lcv;
lostTimer.Dispose();
lostTimer = null;
for (lcv = 0; lcv < numThreads; lcv++)
...{
if (!serverThread[lcv].IsAlive)
threadEnd[lcv].Set(); // Set event if thread is already dead
}
ShuttingDown = true;
// Create a connection to the port to unblock the listener thread
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, this.portNumber);
sock.Connect(endPoint);
//sock.Close();
sock = null;
// Check thread end events and wait for up to 5 seconds.
for (lcv = 0; lcv < numThreads; lcv++)
threadEnd[lcv].WaitOne(5000, false);
}
/**//// <summary>
/// Decription: Open a listener socket and wait for a connection.
/// </summary>
private void StartListening()
...{
// Establish the local endpoint for the socket.
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, this.portNumber);
// 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(1000);
while (!ShuttingDown)
...{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(new AsyncCallback(this.AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
...{
threadEnd[0].Set();
}
}
/**//// <summary>
/// Decription: Call back method to accept new connections.
/// </summary>
/// <param name="ar">Status of an asynchronous operation.</param>
private 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;
state.TimeStamp = DateTime.Now;
try
...{
Interlocked.Increment(ref sockCount);
Monitor.Enter(connectedSocks);
connectedSocks.Add(state);
Monitor.Exit(connectedSocks);
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(this.ReadCallback), state);
if (sockCount > this.maxSockets)
...{
RemoveSocket(state);
//handler.Shutdown(SocketShutdown.Both);
//handler.Close();
handler = null;
state = null;
}
}
catch (SocketException es)
...{
RemoveSocket(state);
}
catch (Exception e)
...{
RemoveSocket(state);
}
}
/// Decription: Open a listener socket and wait for a connection.
/// </summary>
private void StartListening()
...{
// Establish the local endpoint for the socket.
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, this.portNumber);
// 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(1000);
while (!ShuttingDown)
...{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(new AsyncCallback(this.AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
...{
threadEnd[0].Set();
}
}
/**//// <summary>
/// Decription: Call back method to accept new connections.
/// </summary>
/// <param name="ar">Status of an asynchronous operation.</param>
private 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;
state.TimeStamp = DateTime.Now;
try
...{
Interlocked.Increment(ref sockCount);
Monitor.Enter(connectedSocks);
connectedSocks.Add(state);
Monitor.Exit(connectedSocks);
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(this.ReadCallback), state);
if (sockCount > this.maxSockets)
...{
RemoveSocket(state);
//handler.Shutdown(SocketShutdown.Both);
//handler.Close();
handler = null;
state = null;
}
}
catch (SocketException es)
...{
RemoveSocket(state);
}
catch (Exception e)
...{
RemoveSocket(state);
}
}
/**//// <summary>
/// Decription: Call back method to handle incoming data.
/// </summary>
/// <param name="ar">Status of an asynchronous operation.</param>
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.workSocket;
try
...{
// 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.
Monitor.Enter(state);
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
Monitor.Exit(state);
// Check for end-of-file tag.
// If it is not there, read more data.
content = state.sb.ToString();
//if (content.IndexOf("<EOF>") > -1)
if ((content.Length > 0) && ((content[0] != '<') ||
((content[0] == '<') && (content.IndexOf("</message>") > -1))))
...{
// All the data has been read from the
// client. Display it on the console.
//Console.WriteLine("Read {0} bytes from socket. Data: {1}",
// content.Length, content);
// Process the received message
state.TimeStamp = DateTime.Now;
HandleMessages(state, content);
// Echo the data back to the client.
// Send(state, content);
//state.sb.Length = 0;
}
else
...{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(this.ReadCallback), state);
}
}
else
...{ // Disconnected
RemoveSocket(state);
}
}
catch (System.Net.Sockets.SocketException es)
...{
RemoveSocket(state);
if (es.ErrorCode != 64)
...{
Console.WriteLine( string.Format("ReadCallback Socket Exception: {0}, {1}.", es.ErrorCode, es.ToString()));
}
}
catch (Exception e)
...{
RemoveSocket(state);
if (e.GetType().FullName != "System.ObjectDisposedException")
...{
Console.WriteLine(string.Format("ReadCallback Exception: {0}.", e.ToString()));
}
}
}
/**//// <summary>
/// Decription: Send the given data string to the given socket.
/// </summary>
/// <param name="sock">Socket to send data to.</param>
/// <param name="data">The string containing the data to send.</param>
protected void Send(Socket sock, 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.
if (byteData.Length > 0)
sock.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(this.SendCallback), sock);
}
/**//// <summary>
/// Author: Asad Aziz
/// Decription: Call back method to handle outgoing data.
/// </summary>
/// <param name="ar">Status of an asynchronous operation.</param>
protected void SendCallback(IAsyncResult ar)
...{
// Retrieve the socket from the async state object.
Socket handler = (Socket) ar.AsyncState;
try
...{
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
}
catch (Exception e)
...{
}
}
/**//// <summary>
// Description: Find on socket using the identifier as the key.
/**//// </summary>
/// <param name="id">The identifier key associated with a socket.</param>
private Socket FindID(string id)
...{
Socket sock = null;
Monitor.Enter(connectedHT);
if (connectedHT.ContainsKey(id))
sock = (Socket) connectedHT[id];
Monitor.Exit(connectedHT);
return sock;
}
/**//// <summary>
/// Author: Asad Aziz
/// Description: Place the given socket in the connected list.
///
/// Notes:
/// 1) Get the Member ID from the command
/// 2) Add the socket to the connected socket list with its Member ID
/// </summary>
/// <param name="state">The state object containing the socket info.</param>
/// <param name="command">The XML-based message containing the ID that
/// needs to be parsed.</param>
/// <param name="content">Not used in the base method.</param>
virtual protected bool StuffList(StateObject state, string command,
ref string content)
...{
Socket sock = state.workSocket;
string hostID = ReadXML(command, Server.msgConnect, this.connectAttr);
if (hostID != null)
...{
state.id = hostID;
if (hostID == Server.webServer)
...{
Console.WriteLine(string.Format("Host control socket connected {0}!",
this.title));
return true;
}
// Add to connected list
Monitor.Enter(connectedHT);
if (connectedHT.ContainsKey(hostID))
...{
object val = connectedHT[hostID];
connectedHT[hostID] = sock;
connectedHT.Add(sock, val);
Console.WriteLine(string.Format("Socket found in Hasttable!",this.title));
}
else
...{
connectedHT.Add(hostID, sock);
connectedHT.Add(sock, hostID);
Console.WriteLine(string.Format("Socket not found, adding a new socket to hashtable!",this.title));
}
Monitor.Exit(connectedHT);
Console.WriteLine(string.Format("Socket was moved to connected {0} list!",this.title));
return true;
}
return false;
}
/**//// <summary>
/// Description: Remove the socket contained in the given state object
/// from the connected array list and hash table, then close the socket.
/// </summary>
/// <param name="state">The StateObject containing the specific socket
/// to remove from the connected array list and hash table.</param>
virtual protected void RemoveSocket(StateObject state)
...{
Socket sock = state.workSocket;
Monitor.Enter(connectedSocks);
if (connectedSocks.Contains(state))
...{
connectedSocks.Remove(state);
Interlocked.Decrement(ref sockCount);
}
Monitor.Exit(connectedSocks);
Monitor.Enter(connectedHT);
if ((sock != null) && (connectedHT.ContainsKey(sock)))
...{
object sockTemp = connectedHT[sock];
if (connectedHT.ContainsKey(sockTemp))
...{
if (connectedHT.ContainsKey(connectedHT[sockTemp]))
...{
connectedHT.Remove(sock);
if (sock.Equals(connectedHT[sockTemp]))
...{
connectedHT.Remove(sockTemp);
}
else
...{
object val, key = sockTemp;
while (true)
...{
val = connectedHT[key];
if (sock.Equals(val))
...{
connectedHT[key] = sockTemp;
break;
}
else if (connectedHT.ContainsKey(val))
key = val;
else // The chain is broken
break;
}
}
}
else
...{
Console.WriteLine(string.Format("Socket is not in the {0} connected hash table!", this.title));
}
}
}
Monitor.Exit(connectedHT);
if (sock != null)
...{
//if (sock.Connected)
// sock.Shutdown(SocketShutdown.Both);
sock.Close();
sock = null;
state.workSocket = null;
state = null;
}
}
}
/// Decription: Call back method to handle incoming data.
/// </summary>
/// <param name="ar">Status of an asynchronous operation.</param>
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.workSocket;
try
...{
// 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.
Monitor.Enter(state);
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
Monitor.Exit(state);
// Check for end-of-file tag.
// If it is not there, read more data.
content = state.sb.ToString();
//if (content.IndexOf("<EOF>") > -1)
if ((content.Length > 0) && ((content[0] != '<') ||
((content[0] == '<') && (content.IndexOf("</message>") > -1))))
...{
// All the data has been read from the
// client. Display it on the console.
//Console.WriteLine("Read {0} bytes from socket. Data: {1}",
// content.Length, content);
// Process the received message
state.TimeStamp = DateTime.Now;
HandleMessages(state, content);
// Echo the data back to the client.
// Send(state, content);
//state.sb.Length = 0;
}
else
...{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(this.ReadCallback), state);
}
}
else
...{ // Disconnected
RemoveSocket(state);
}
}
catch (System.Net.Sockets.SocketException es)
...{
RemoveSocket(state);
if (es.ErrorCode != 64)
...{
Console.WriteLine( string.Format("ReadCallback Socket Exception: {0}, {1}.", es.ErrorCode, es.ToString()));
}
}
catch (Exception e)
...{
RemoveSocket(state);
if (e.GetType().FullName != "System.ObjectDisposedException")
...{
Console.WriteLine(string.Format("ReadCallback Exception: {0}.", e.ToString()));
}
}
}
/**//// <summary>
/// Decription: Send the given data string to the given socket.
/// </summary>
/// <param name="sock">Socket to send data to.</param>
/// <param name="data">The string containing the data to send.</param>
protected void Send(Socket sock, 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.
if (byteData.Length > 0)
sock.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(this.SendCallback), sock);
}
/**//// <summary>
/// Author: Asad Aziz
/// Decription: Call back method to handle outgoing data.
/// </summary>
/// <param name="ar">Status of an asynchronous operation.</param>
protected void SendCallback(IAsyncResult ar)
...{
// Retrieve the socket from the async state object.
Socket handler = (Socket) ar.AsyncState;
try
...{
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
}
catch (Exception e)
...{
}
}
/**//// <summary>
// Description: Find on socket using the identifier as the key.
/**//// </summary>
/// <param name="id">The identifier key associated with a socket.</param>
private Socket FindID(string id)
...{
Socket sock = null;
Monitor.Enter(connectedHT);
if (connectedHT.ContainsKey(id))
sock = (Socket) connectedHT[id];
Monitor.Exit(connectedHT);
return sock;
}
/**//// <summary>
/// Author: Asad Aziz
/// Description: Place the given socket in the connected list.
///
/// Notes:
/// 1) Get the Member ID from the command
/// 2) Add the socket to the connected socket list with its Member ID
/// </summary>
/// <param name="state">The state object containing the socket info.</param>
/// <param name="command">The XML-based message containing the ID that
/// needs to be parsed.</param>
/// <param name="content">Not used in the base method.</param>
virtual protected bool StuffList(StateObject state, string command,
ref string content)
...{
Socket sock = state.workSocket;
string hostID = ReadXML(command, Server.msgConnect, this.connectAttr);
if (hostID != null)
...{
state.id = hostID;
if (hostID == Server.webServer)
...{
Console.WriteLine(string.Format("Host control socket connected {0}!",
this.title));
return true;
}
// Add to connected list
Monitor.Enter(connectedHT);
if (connectedHT.ContainsKey(hostID))
...{
object val = connectedHT[hostID];
connectedHT[hostID] = sock;
connectedHT.Add(sock, val);
Console.WriteLine(string.Format("Socket found in Hasttable!",this.title));
}
else
...{
connectedHT.Add(hostID, sock);
connectedHT.Add(sock, hostID);
Console.WriteLine(string.Format("Socket not found, adding a new socket to hashtable!",this.title));
}
Monitor.Exit(connectedHT);
Console.WriteLine(string.Format("Socket was moved to connected {0} list!",this.title));
return true;
}
return false;
}
/**//// <summary>
/// Description: Remove the socket contained in the given state object
/// from the connected array list and hash table, then close the socket.
/// </summary>
/// <param name="state">The StateObject containing the specific socket
/// to remove from the connected array list and hash table.</param>
virtual protected void RemoveSocket(StateObject state)
...{
Socket sock = state.workSocket;
Monitor.Enter(connectedSocks);
if (connectedSocks.Contains(state))
...{
connectedSocks.Remove(state);
Interlocked.Decrement(ref sockCount);
}
Monitor.Exit(connectedSocks);
Monitor.Enter(connectedHT);
if ((sock != null) && (connectedHT.ContainsKey(sock)))
...{
object sockTemp = connectedHT[sock];
if (connectedHT.ContainsKey(sockTemp))
...{
if (connectedHT.ContainsKey(connectedHT[sockTemp]))
...{
connectedHT.Remove(sock);
if (sock.Equals(connectedHT[sockTemp]))
...{
connectedHT.Remove(sockTemp);
}
else
...{
object val, key = sockTemp;
while (true)
...{
val = connectedHT[key];
if (sock.Equals(val))
...{
connectedHT[key] = sockTemp;
break;
}
else if (connectedHT.ContainsKey(val))
key = val;
else // The chain is broken
break;
}
}
}
else
...{
Console.WriteLine(string.Format("Socket is not in the {0} connected hash table!", this.title));
}
}
}
Monitor.Exit(connectedHT);
if (sock != null)
...{
//if (sock.Connected)
// sock.Shutdown(SocketShutdown.Both);
sock.Close();
sock = null;
state.workSocket = null;
state = null;
}
}
}
- Asynchronous server socket using C#
- Asynchronous TCP server using coroutines
- Asynchronous Programming in C# 5.0 using async and await
- Asynchronous programming using coroutines
- Asynchronous Socket Lib
- Asynchronous socket communication
- 译文:异步Socket服务器与客户端(An Asynchronous Socket Server and Client)
- [转载]异步Socket服务器与客户端(An Asynchronous Socket Server and Client)
- [转载]异步Socket服务器与客户端(An Asynchronous Socket Server and Client)
- C# server socket 异步
- C# Server Socket
- C# asynchronous TcpListener
- C# concise asynchronous TcpClient
- C# asynchronous TcpListener
- c# socket(server and client)
- C# 2010 socket client-server
- A Chat Application Using Asynchronous TCP Sockets
- Using epoll() For Asynchronous Network Programming
- 一个高效的数据分页的存储过程
- 从数据库中读取图片文件和将图片和写入到数据库中
- java高级应用之框架篇
- SYMBIAN中的字符串操作
- 职业规划就像软件工程
- Asynchronous server socket using C#
- 提高asp.net应用程序性能的方法
- 一个用ASP生成html的新方法
- 利用OpenCV做的摄像头互动游戏以及源代码
- TcpListener Class
- [转载]UNIX程序的链接
- 第一篇就要开始了,呵呵
- Alpha颜色混合的魔法 上篇 “法术篇”
- 查找并释放窗体