private void AcceptCallback(IAsyncResult ar) { Socket handlerSocket = null; try { //喚醒多個執行緒,讓進入Waitting回到Running狀態。 // Signal the main thread to continue. SignalEvent.Set(); //AsyncState 取得符合或包含非同步作業資訊的使用者定義的物件 // Get the socket that handles the client request. Socket listener = (Socket)ar.AsyncState; // 取得主要的socket, 其中包含使用者定義的物件及handles the client request //將主要正在 listening(正在連入的client Socket)轉交給另一個臨時的handlerSocket變數,並且結束接受此一客戶端的連線 handlerSocket = listener.EndAccept(ar); //取得遠端節點的EndPoint handler.RemoteEndPoint.ToString().Split(':')[0] //SocketInformLog("A client has connected. client ip : " + handlerSocket.RemoteEP.ToString().Split(':')[0] + ", Client Socket HashCode = " + handlerSocket.GetHashCode() + Environment.NewLine); gClientSocketList.Add(handlerSocket); // Create the state object. SocketStateObj state = new SocketStateObj(); state.workSocket = handlerSocket; // 假設已連線的客戶端要傳送資料時,所指定的回呼函式-ReadCallback,這也是C#中的delagate型別 // 定義當Socket 接收到資料時要交給哪一個函數處理,這裡定義了BeginReceive() // 參數第一個為存放的位置,為byte[],傳入的資料會置於此陣列中;第二參數為啟始位置、第三參數為一次接收的最大長度; // 第四為封包的旗標,例如標記為"廣播封包"之類, // 第五參數為開始接受資料時叫用的回呼函式,用AsyncCallback實體化指定ReadCallback為回呼函式,所以當客戶端將資料傳進來時,ReadCallback函式會被叫用; // 第六為狀態的參數,這個是用戶自訂,當回呼函式ReadCallback被叫用 時,此參數的值會被傳遞到ReadCallback,其中包含Socket,但是回呼函式仍會曉得是哪一個Socket在傳送資料。 handlerSocket.BeginReceive(state.buffer, 0, SocketStateObj.BufferSize, SocketFlags.None, new AsyncCallback(ReadCallback), state); } catch (Exception e) { FireExceptionEvent(LEVSocketExceptionType.ConnectException, handlerSocket, "[AcceptCallback] An error occurred when attempting to access the socket or to receive data from a connected Socket." + Environment.NewLine + e); } }
private void ReadCallback(IAsyncResult ar) { String content = String.Empty; //重新取回 state object // Retrieve the state object and the handler socket from the asynchronous state object. SocketStateObj state = (SocketStateObj)ar.AsyncState; Socket handler = state.workSocket; try { //SocketInformLog("Client is waitting and begining to receive data. client ip : " + handler.RemoteEndPoint.ToString().Split(':')[0] + ", Client Socket HashCode = " + handler.GetHashCode() + Environment.NewLine); //叫用 EndReceive 完成指定的非同步接收作業, 參數asyn (ar) 識別要完成的非同步接收作業,並要從其中擷取最終結果。 // Read data from the client socket. int bytesRead = handler.EndReceive(ar); //SocketInformLog("ReadCallback; byteRead = " + bytesRead); if (bytesRead > 0) { #region msdn code // There might be more data, so store the data received so far. //state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); //state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, bytesRead)); byte[] currentRead = new byte[bytesRead]; Array.Copy(state.buffer, currentRead, bytesRead); state.listBuffer.AddRange(currentRead); //FireReceivingEvent(SocketReceivingTyp.Fragment, handler, currentRead); //content = state.sb.ToString(); //content = Encoding.UTF8.GetString(state.buffer, 0, bytesRead); //only for compare, so use Encoding.ASCII content = Encoding.ASCII.GetString(state.buffer, 0, bytesRead); //SocketInformLog("Client is receiving data. client ip : " + handler.RemoteEndPoint.ToString().Split(':')[0] + ", Client Socket HashCode = " + handler.GetHashCode() + Environment.NewLine); //SocketInformLog("ReadCallback; content = " + content + Environment.NewLine); // Check for end-of-file tag. If it is not there, read more data. //if(LEVSocketUtilities.ByteArrayIndexOf(currentRead, 0, gOldVer_EOF_TokenBArray) > -1) //if (content.IndexOf("<EOF>") > -1) if (content.IndexOf(_OldVer_EOF_Token) > -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); byte[] packet = state.listBuffer.ToArray <byte>(); int idx = LEVSocketUtilities.ByteArrayIndexOf(packet, Encoding.ASCII.GetBytes(_OldVer_EOF_Token)); if (idx > -1) { byte[] cpy = new byte[idx]; Array.Copy(packet, cpy, idx); FireReceivingEvent(SocketReceivingTyp.OldVerWholePacket, handler, cpy); } //SocketInformLog("ReadCallback; Get <EOF> and Send back to client." + Environment.NewLine); //Send_PreviousVer(handler, "get Data finish"); state.listBuffer.Clear(); //state.sb.Clear(); } else if (LEVSocketUtilities.ByteArrayIndexOf(currentRead, SocketCmdToken._packetDataEOF_.ToString()) > -1) { byte[] packet = state.listBuffer.ToArray <byte>(); int idx = LEVSocketUtilities.ByteArrayIndexOf(packet, SocketCmdToken._packetDataEOF_.ToString()); if (idx > -1) { byte[] cpy = new byte[idx]; Array.Copy(packet, cpy, idx); FireReceivingEvent(SocketReceivingTyp.WholePacket, handler, cpy); } //FireReceivingEvent(SocketReceivingTyp.WholePacket, handler, state.listBuffer.ToArray<byte>()); state.listBuffer.Clear(); } else { //SocketInformLog("ReadCallback; Not all data received. Get more." + Environment.NewLine); // Not all data received. Get more. } handler.BeginReceive(state.buffer, 0, SocketStateObj.BufferSize, SocketFlags.None, new AsyncCallback(ReadCallback), state); #endregion #region modify code // All data received. Get next message. // Not all data received. Get more. //handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); //new //// There might be more data, so store the data received so far. ////state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); //state.sb.Append(Encoding.UTF8.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) //{ // //// Reply to the client. // //Send(handler, resultData); // // All data received. Get next message. // handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); //new //} //else //{ // // Not all data received. Get more. // handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); //} #endregion } } catch (SocketException e) { ///////////////////////////////////////////////////////////// //if (ex.ErrorCode == 10054 || ex.ErrorCode == 10053) //{ // log.Write(client_ip + " has left"); // LogHelper.WriteServerDataLog(LogHelper.MsgType.Normal, LogHelper.Action.ClientLefted, // client_ip, "Client has left"); //} //else //{ // //Console.WriteLine(ex); // log.Write("ReadCallBack1: " + ex.Message); //2013/8/22: Log exception message // LogHelper.WriteServerDataLog(LogHelper.MsgType.Exception, LogHelper.Action.ServerMessages, // "-", "ReadCallBack1: " + ex.Message); //} //SocketInformLog("[SocketException][ReadCallback] An error occurred when attempting to access the socket or to receive data from a connected Socket. ==> " + e + Environment.NewLine); //throw new Exception("[SocketException] An error occurred when attempting to access the socket or to receive data from a connected Socket. ==> " + e); //SocketInformLog("handlerSocket Close. HashCode = " + handler.GetHashCode() + Environment.NewLine); FireExceptionEvent(LEVSocketExceptionType.DisConnectException, handler, "[SocketException][ReadCallback] An error occurred when attempting to access the socket or to receive data from a connected Socket." + Environment.NewLine + e); closeClientSocket(handler, true, false); FireSocketMsgEvent(LEVSocketEventType.ClientDisconnect, handler, "Client is going to be disconnected."); } catch (Exception e) { //SocketInformLog("[Exception][ReadCallback] An error occurred when attempting to access the socket or to receive data from a connected Socket. ==> " + e + Environment.NewLine); FireExceptionEvent(LEVSocketExceptionType.DisConnectException, handler, "[Exception][ReadCallback] An error occurred when attempting to access the socket or to receive data from a connected Socket." + Environment.NewLine + e); //throw new Exception("[Exception] An error occurred when attempting to access the socket or to receive data from a connected Socket. ==> " + e); //log.Write("ReadCallBack2: " + e.Message); //2013/8/22: Log exception message //LogHelper.WriteServerDataLog(LogHelper.MsgType.Exception, LogHelper.Action.ServerMessages, // "-", "ReadCallBack2: " + e.Message); } }