/// <summary> /// 监听Socket接受处理 /// </summary> /// <param name="e">SocketAsyncEventArg associated with the completed accept operation.</param> private void ProcessAccept(SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { Socket s = e.AcceptSocket;//和客户端关联的socket if (s.Connected) { try { Interlocked.Increment(ref _clientCount);//原子操作加1 SocketAsyncEventArgs asyniar = _objectPool.Pop(); //asyniar.UserToken = s; //客户端信息 AsyncUserToken userToken = (AsyncUserToken)asyniar.UserToken; userToken.ReceiveEventArgs = asyniar; userToken.Socket = e.AcceptSocket; userToken.ConnectTime = DateTime.Now; userToken.Remote = e.AcceptSocket.RemoteEndPoint; userToken.IPAddress = ((IPEndPoint)(e.AcceptSocket.RemoteEndPoint)).Address; //userToken.SendEventArgs = asyniar; lock (m_clients) { m_clients.Add(userToken); } //Log4Debug(String.Format("客户 {0} 连入, 共有 {1} 个连接。", s.RemoteEndPoint.ToString(), _clientCount)); //SockList.Add(s); if (!s.ReceiveAsync(asyniar))//投递接收请求 { ProcessReceive(asyniar); } } catch (SocketException ex) { //Log4Debug(String.Format("接收客户 {0} 数据出错, 异常信息: {1} 。", s.RemoteEndPoint, ex.ToString())); //TODO 异常处理 } if (e.SocketError == SocketError.OperationAborted) { return; } //投递下一个接受请求 StartAccept(e); } } else if (e.SocketError == SocketError.ConnectionReset && e.BytesTransferred == 0) { //Log4Debug("Client: 服务器断开连接 "); CloseClientSocket(e); } }
/// <summary> /// client 连接或断开时 /// </summary> /// <param name="num"></param> /// <param name="token"></param> static void m_socket_ClientNumberChange(int num, AsyncUserToken token) { string msg = ""; if (num > 0) { msg = string.Format("{0},{1}已连接", num, token.Remote.ToString()); Log.Info(msg); } if (num < 0) { msg = string.Format("{0},{1}断开连接", num, token.Remote.ToString()); } Log.Info(msg); }
private void ProcessSend(SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { AsyncUserToken token = (AsyncUserToken)e.UserToken; //Done transmitting e.SetBuffer(e.Offset, receiveBufferSize); //Restore buffer size for the receiver //Start an asynchronous request to receive if (!token.Socket.ReceiveAsync(e)) //I/O completed synchronously, no event raised, must handle now { ProcessReceive(e); } } else { CloseClientSocket(e); } }
// This method is invoked when an asynchronous send operation completes. // The method issues another receive on the socket to read any additional // data sent from the client // // <param name="e"></param> private void ProcessSend(SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { // done echoing data back to the client AsyncUserToken token = (AsyncUserToken)e.UserToken; // read the next block of data send from the client bool willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { ProcessReceive(e); } } else { CloseClientSocket(e); } }
/// <summary> /// 发送完成时处理函数 /// </summary> /// <param name="e">与发送完成操作相关联的SocketAsyncEventArg对象</param> private void ProcessSend(SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { //Socket s = (Socket)e.UserToken; AsyncUserToken token = (AsyncUserToken)e.UserToken; //TODO if (!token.Socket.ReceiveAsync(e))//为接收下一段数据,投递接收请求,这个函数有可能同步完成,这时返回false,并且不会引发SocketAsyncEventArgs.Completed事件 { //同步接收时处理接收完成事件 //ProcessReceive(e); ProcessSend(e); } } else { CloseClientSocket(e); } }
private void CloseClientSocket(SocketAsyncEventArgs e) { AsyncUserToken token = e.UserToken as AsyncUserToken; // Close the socket associated with the client try { token.Socket.Shutdown(SocketShutdown.Send); } catch (Exception ex) { Debug.WriteLine("Error shuttin down socket: Source {0}, Message: {1}", ex.Source, ex.Message); } token.Socket.Close(); _maxNumberAcceptedClients.Release(); Interlocked.Decrement(ref _numConnectedSockets); Debug.WriteLine("Connecttion dropped, {0} remaining.", _numConnectedSockets); Push(e); //Free the SocketAsyncEventArg, so that they can be reused by another client }
private void ProcessAccept(SocketAsyncEventArgs e) { try { Interlocked.Increment(ref m_clientCount); // Get the socket for the accepted client connection and put it into the //ReadEventArg object user token SocketAsyncEventArgs readEventArgs = m_pool.Pop(); AsyncUserToken userToken = (AsyncUserToken)readEventArgs.UserToken; userToken.usernamr = "Mtt"; userToken.Socket = e.AcceptSocket; userToken.ConnectTime = DateTime.Now; userToken.Remote = e.AcceptSocket.RemoteEndPoint; userToken.IPAddress = ((IPEndPoint)(e.AcceptSocket.RemoteEndPoint)).Address; lock (m_clients) { m_clients.Add(userToken); } if (ClientNumberChange != null) { ClientNumberChange(1, userToken); } if (!e.AcceptSocket.ReceiveAsync(readEventArgs)) { ProcessReceive(readEventArgs); } } catch (Exception me) { Console.WriteLine(me.Message); } // Accept the next connection request if (e.SocketError == SocketError.OperationAborted) { return; } StartAccept(e); }
private void CloseClientSocket(SocketAsyncEventArgs e) { AsyncUserToken token = e.UserToken as AsyncUserToken; // close the socket associated with the client try { token.Socket.Shutdown(SocketShutdown.Send); } // throws if client process has already closed catch (Exception) { } token.Socket.Close(); // decrement the counter keeping track of the total number of clients connected to the server Interlocked.Decrement(ref m_numConnectedSockets); // Free the SocketAsyncEventArg so they can be reused by another client m_readWritePool.Push(e); m_maxNumberAcceptedClients.Release(); Console.WriteLine("A client has been disconnected from the server. There are {0} clients connected to the server", m_numConnectedSockets); }
public override void MessageReceive(AsyncUserToken token, int cmd, IMessage message) { Cmd command = (Cmd)cmd; switch (command) { case Cmd.GmCommand: break; case Cmd.Login: login.MessageReceive(token, cmd, message); break; case Cmd.CreateRole: break; case Cmd.SetRolename: break; case Cmd.SceneLoad: break; case Cmd.SceneRole: break; case Cmd.MailOpen: break; case Cmd.MailAtch: break; case Cmd.MailDel: break; default: break; } }
/// <summary> /// 停止服务 /// </summary> public void Stop() { foreach (var item in m_clients) { try { AsyncUserToken token = item; token.Socket.Shutdown(SocketShutdown.Both); } catch (Exception) { } } try { if (m_clients.Count > 0) { listenSocket.Shutdown(SocketShutdown.Both); } } catch (Exception e)//当socket 无连接时(即没有可用已连接的client) { // listenSocket.Disconnect(false);///因为无可用的socket连接,此方法不可用 Console.WriteLine(e.Message); } finally { listenSocket.Close(); //通知界面,server已经停止 if (ServerStopedEvent != null) { ServerStopedEvent(); } lock (m_clients) { m_clients.Clear(); } } }
//关闭客户端 private void CloseClientSocket(SocketAsyncEventArgs e) { AsyncUserToken token = e.UserToken as AsyncUserToken; lock (m_clients) { m_clients.Remove(token); } //如果有事件,则调用事件,发送客户端数量变化通知 if (ClientNumberChange != null) { ClientNumberChange(-1, token); } // close the socket associated with the client try { token.Socket.Shutdown(SocketShutdown.Send); } catch (Exception) { } token.Socket.Close(); // decrement the counter keeping track of the total number of clients connected to the server Interlocked.Decrement(ref m_clientCount); m_maxNumberAcceptedClients.Release(); // Free the SocketAsyncEventArg so they can be reused by another client e.UserToken = new AsyncUserToken(); m_pool.Push(e); }
// This method is invoked when an asynchronous receive operation completes. // If the remote host closed the connection, then the socket is closed. // If data was received then the data is echoed back to the client. // private void ProcessReceive(SocketAsyncEventArgs e) { // check if the remote host closed the connection AsyncUserToken token = (AsyncUserToken)e.UserToken; if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { //increment the count of the total bytes receive by the server Interlocked.Add(ref m_totalBytesRead, e.BytesTransferred); Console.WriteLine("The server has read a total of {0} bytes", m_totalBytesRead); //echo the data received back to the client e.SetBuffer(e.Offset, e.BytesTransferred); bool willRaiseEvent = token.Socket.SendAsync(e); if (!willRaiseEvent) { ProcessSend(e); } } else { CloseClientSocket(e); } }
public override void ClientConnect(AsyncUserToken token) { Console.WriteLine($"[ {token.UserSocket.RemoteEndPoint.ToString()} ] 连接"); }
public override void ClientClose(AsyncUserToken token, string error) { Console.WriteLine($"[ {token.UserSocket.ToString()} ] 断开连接,{error}"); }
// This method is invoked when an asynchronous receive operation completes. // If the remote host closed the connection, then the socket is closed. // If data was received then the data is echoed back to the client. // private void ProcessReceive(SocketAsyncEventArgs e) { try { // check if the remote host closed the connection AsyncUserToken token = (AsyncUserToken)e.UserToken; if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { //读取数据 byte[] data = new byte[e.BytesTransferred]; Array.Copy(e.Buffer, e.Offset, data, 0, e.BytesTransferred); lock (token.Buffer) { token.Buffer.AddRange(data); } //注意:你一定会问,这里为什么要用do-while循环? //如果当客户发送大数据流的时候,e.BytesTransferred的大小就会比客户端发送过来的要小, //需要分多次接收.所以收到包的时候,先判断包头的大小.够一个完整的包再处理. //如果客户短时间内发送多个小数据包时, 服务器可能会一次性把他们全收了. //这样如果没有一个循环来控制,那么只会处理第一个包, //剩下的包全部留在token.Buffer中了,只有等下一个数据包过来后,才会放出一个来. do { //判断包的长度 byte[] lenBytes = token.Buffer.GetRange(0, 4).ToArray(); int packageLen = BitConverter.ToInt32(lenBytes, 0); if (packageLen > token.Buffer.Count - 4) { //长度不够时,退出循环,让程序继续接收 break; } //包够长时,则提取出来,交给后面的程序去处理 byte[] rev = token.Buffer.GetRange(4, packageLen).ToArray(); //从数据池中移除这组数据 lock (token.Buffer) { token.Buffer.RemoveRange(0, packageLen + 4); } //将数据包交给后台处理,这里你也可以新开个线程来处理.加快速度. if (ReceiveClientData != null) { ReceiveClientData(token, rev); } //这里API处理完后,并没有返回结果,当然结果是要返回的,却不是在这里, 这里的代码只管接收. //若要返回结果,可在API处理中调用此类对象的SendMessage方法,统一打包发送.不要被微软的示例给迷惑了. } while (token.Buffer.Count > 4); //继续接收. 为什么要这么写,请看Socket.ReceiveAsync方法的说明 if (!token.Socket.ReceiveAsync(e)) { this.ProcessReceive(e); } } else { CloseClientSocket(e); } } catch (Exception xe) { Console.WriteLine(xe.Message + "\r\n" + xe.StackTrace); } }