public int connectSocket(int reqID, ASSocket socket, string ipaddress, int port) { long sel = 1; ASNetService selected = theServices[sel]; return(selected.connectSocket(reqID, socket, ipaddress, port)); }
private void ReleaseSocket(ASSocket socket) { lock (this) { int iocount = socket.exitIO(); if (0 == iocount) { // 이 경우에는 Dispose()를 위해 Close()할 필요는 없다? //socket.tcpclient.GetStream().Close(); //socket.tcpclient.Close(); //socket.sendlist.Clear(); // 객체파괴가 어떻게 일어날지 모르니, desc는 값을 복사해서 사용하자. theSockets.Remove(socket.theDESC.managedID); ASSOCKDESC desc = new ASSOCKDESC(); desc.createTick = socket.theDESC.createTick; desc.managedID = socket.theDESC.managedID; desc.theSender = socket.theDESC.theSender; // socket에 대해 메모리 풀링이 필요하다면, clone()과 아래 함수가 풀링에 대해 어떻게 처리할지 담당하면된다. // socket이 구체적으로 어떤 타입인지에 따라 풀링매니저가 달라져야 하기 때문에, asio계층에선 담당하지 않는다. theReceiver.notifyReleaseSocket(desc, socket); } } }
private void ProcessReceive(SocketAsyncEventArgs e) { ASSocket token = (ASSocket)e.UserToken; try { if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { token.handleReceived(e.BytesTransferred, e.Buffer, e.Offset, theReceiver); bool willRaiseEvent = token.tcpclient.Client.ReceiveAsync(e); if (!willRaiseEvent) { // 이 소켓이 대해 계속 즉시 완료가 일어나면, 이 워커쓰레드는 이 소켓처리만 계속하게 될것이다. 하지만 그런경우는 드물다.. ProcessReceive(e); } } else { Console.WriteLine(DateTime.Now.ToString() + " - processreceive " + e.BytesTransferred + " " + e.SocketError); // e를 재사용하려면 e.Completed -= IO_Completed; 하면된다. 현재는 버퍼만 풀링하고 SocketAsyncEventArgs는 풀링하지 않는다. e.Completed -= IO_Completed; asiomanager.ReleaseSAEA(e); ReleaseSocket(token); } } catch (Exception ex) { Console.WriteLine(DateTime.Now.ToString() + " - processreceive " + ex.Message); // 응용계층에서 프로토콜 파싱하는 과정에서 발생한 예외도 여기서 캐치되어 세션종료만을 해서 프로세스가 종료되지 않는다. e.Completed -= IO_Completed; asiomanager.ReleaseSAEA(e); ReleaseSocket(token); } }
public Acceptor(ASIOManager asio, ASSocket ap, string aipaddress, int aport) { theASIO = asio; prototype = ap; ipaddress = aipaddress; port = aport; state = eState.eState_None; }
private void ProcessSend(SocketAsyncEventArgs e) { // 다 못보내져서 남은것을 재전송해야하는 경우는??? ASSocket token = (ASSocket)e.UserToken; e.Completed -= IO_Completed; asiomanager.ReleaseSAEA(e); ReleaseSocket(token); }
internal int registerSocket(TcpClient acceptedclient, ASSocket prototype) { ASNetService selected = theServices[currentid]; int ret = selected.registerSocket(acceptedclient, prototype); if (maxcnt < ++currentid) { currentid = 1; } return(ret); }
// c#에선 TcpListener.AcceptTcpClient가 반환하는 TcpClient객체레퍼런스를 넘겨줘야한다. // 즉 c++에선 int 값을 넘겨줬지만, c#에선 TcpClient 이 객체를 기본 베이스로 사용해야 한다. public int registerSocket(TcpClient acceptedclient, ASSocket prototype) { // 락을 걸어야하나? lock (this) { // 개체하나를 클론하고 ASSocket aSocket = prototype.Clone() as ASSocket; aSocket.SetTcpClient(acceptedclient); aSocket.theDESC.theSender = this; // 관리리스트에 등록 - need lock theSockets.Add(aSocket.theDESC.managedID, aSocket); // 리시버에게 // 객체파괴가 어떻게 일어날지 모르니, desc는 값을 복사해서 사용하자. ASSOCKDESC desc = new ASSOCKDESC(); desc.createTick = aSocket.theDESC.createTick; desc.managedID = aSocket.theDESC.managedID; desc.theSender = aSocket.theDESC.theSender; theReceiver.notifyRegisterSocket(desc, aSocket.remoteAddress); // 1.1 async 버전으로 업그레이드 aSocket.enterIO(); // key saea얻어오기 실패하면 메모리부족이기 때문에, 프로세스를 죽여야한다. SocketAsyncEventArgs readEventArgs = asiomanager.RetreiveSAEA();// new SocketAsyncEventArgs();//= saeaPool.pop(); // saeaPool from the ASIOManager try { readEventArgs.Completed += new EventHandler <SocketAsyncEventArgs>(IO_Completed); readEventArgs.UserToken = aSocket; bool willRaiseEvent = aSocket.tcpclient.Client.ReceiveAsync(readEventArgs); if (!willRaiseEvent) { ProcessReceive(readEventArgs); // 위에서 releaseSocket이 되면, 아래 예외처리는 수행되지 않는다. } } catch (Exception ex) { Console.WriteLine(DateTime.Now.ToString() + " - registerSocket " + ex.Message); // releasesocket을 수정하지 말고 각 문맥에서 releaseSAEA를 호출하자 if (null != readEventArgs) { readEventArgs.Completed -= IO_Completed; asiomanager.ReleaseSAEA(readEventArgs); } ReleaseSocket(aSocket); } } return(0); }
public int connectSocket(int reqID, ASSocket socket, string ipaddress, int port) { lock (this) { if (true == theSockets.ContainsKey(socket.theDESC.managedID)) { return((int)MyErrorCode.AlreadyPostConnect); } // 동일한 socket에 대해 connect를 또 요청할수 있으니 미리 컨테이너에 추가하고 하자. theSockets.Add(socket.theDESC.managedID, socket); ConnectFrame connectFrame = new ConnectFrame(); connectFrame.reqID = reqID; connectFrame.socket = socket; connectFrame.socket.theDESC.theSender = this; socket.tcpclient = new TcpClient(AddressFamily.InterNetwork); socket.tcpclient.BeginConnect(ipaddress, port, new AsyncCallback(ResultConnect), connectFrame); } return(0); }
public int releaseASSOCKDESC(ASSOCKDESC sockdesc) { ASSocket.releaseUID(sockdesc.managedID); return(0); }