Click here to Skip to main content
15,893,588 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
in my code soket is received aync. and in the receive callback there is Send Message.

so callback is looped always.

received-send-received-send .......

in this situation how can i interrupted this loop and quit.

i make quit button but it doesn't work. only i click fast many times.

C#
public class AsyncObject
{
    public Byte[] Buffer;
    public Socket WorkingSocket;
    public AsyncObject(Int32 bufferSize)
    {
        Buffer = new Byte[bufferSize];
    }
}

private Socket _mServerSocket;
private Socket _mSend;
private AsyncCallback _mFnReceiveHandler;
private AsyncCallback _mFnSendHandler;
private AsyncCallback _mFnAcceptHandler;
public void StartServer()
{
    if (_mServerSocket != null)
    {
        if (_mServerSocket.Connected)
        {
            SetText(richTextBox1, "이미 연결되어있습니다.\n");

        }
        SetText(richTextBox1, "이미 연결되어있습니다.\n");
        return;
    }

    // 비동기 작업에 사용될 대리자를 초기화합니다.
    _mFnReceiveHandler = HandleDataReceive;
    _mFnSendHandler = HandleDataSend;
    _mFnAcceptHandler = HandleClientConnectionRequest;

    // TCP 통신을 위한 소켓을 생성합니다.
    _mServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    // 특정 포트에서 모든 주소로부터 들어오는 연결을 받기 위해 포트를 바인딩합니다.
    // 사용한 포트: 8234
    _mServerSocket.Bind(new IPEndPoint(IPAddress.Parse("192.168.0.201"), 8234));
    // 연결 요청을 받기 시작합니다.
    _mServerSocket.Listen(5);

    // BeginAccept 메서드를 이용해 들어오는 연결 요청을 비동기적으로 처리합니다.
    // 연결 요청을 처리하는 함수는 handleClientConnectionRequest 입니다.
    SetText(richTextBox1, "연결중입니다.\n");
    _mServerSocket.BeginAccept(_mFnAcceptHandler, _mServerSocket);

}

public void StopServer(object sender, EventArgs e)
{
    //Thread.Sleep(1000);
    _isClose = true;
    if (_mServerSocket != null)
    {
        if (_mServerSocket.Connected || _mServerSocket.IsBound)
            _mServerSocket.Close();
        _mServerSocket = null;
    }
    if (_mSend != null)
    {
        if (_mSend.Connected)
        {
            _mSend.Disconnect(true);
            _mSend.Close();
        }
        _mSend = null;
    }

    SetText(richTextBox1, "서버가 닫혔습니다.\n");
}

public void SendMessage(String message)
{
    // 추가 정보를 넘기기 위한 변수 선언
    // 크기를 설정하는게 의미가 없습니다.
    // 왜냐하면 바로 밑의 코드에서 문자열을 유니코드 형으로 변환한 바이트 배열을 반환하기 때문에
    // 최소한의 크기르 배열을 초기화합니다.
    if(_mSend == null) return;
    if (message.Length==0) return;
    string sendmessage = message + "\n";
    var ao = new AsyncObject(1) { Buffer = Encoding.UTF8.GetBytes(sendmessage), WorkingSocket = _mSend };
    try
    {
        // 전송 시작!
        _mSend.BeginSend(ao.Buffer, 0, ao.Buffer.Length, SocketFlags.None, _mFnSendHandler, ao);
    }
    catch (SocketException secException)
    {
        MessageBox.Show(secException.ToString());
    }

}

private void HandleClientConnectionRequest(IAsyncResult ar)
{
    try
    {
        // 클라이언트의 연결 요청을 수락합니다.
        Socket sockClient = _mServerSocket.EndAccept(ar);
        _mSend = sockClient;
        // 4096 바이트의 크기를 갖는 바이트 배열을 가진 AsyncObject 클래스 생성
        var ao = new AsyncObject(4096);
        SetText(richTextBox1, sockClient.RemoteEndPoint + "의 연결 요청 수락\n");
        // 작업 중인 소켓을 저장하기 위해 sockClient 할당
        ao.WorkingSocket = sockClient;
        _isClose = false;

        // 비동기적으로 들어오는 자료를 수신하기 위해 BeginReceive 메서드 사용!
        sockClient.BeginReceive(ao.Buffer, 0, ao.Buffer.Length, SocketFlags.None, _mFnReceiveHandler, ao);
    }
    catch (ObjectDisposedException)
    {
    }
    catch (SocketException)
    {
    }
    catch (NullReferenceException)
    {
    }
}
private void HandleDataReceive(IAsyncResult ar)
{
    try
    {

        // 넘겨진 추가 정보를 가져옵니다.
        // AsyncState 속성의 자료형은 Object 형식이기 때문에 형 변환이 필요합니다~!
        var ao = (AsyncObject) ar.AsyncState;

        // 자료를 수신하고, 수신받은 바이트를 가져옵니다.
        Int32 recvBytes = ao.WorkingSocket.EndReceive(ar);
        if (!ao.WorkingSocket.Connected) return;
        // 수신받은 자료의 크기가 1 이상일 때에만 자료 처리
        if (recvBytes > 0)
        {
            SetText(richTextBox1, "메세지 받음: " + Encoding.UTF8.GetString(ao.Buffer));
            SetText(richTextBox1, "\n");
        }
        // 자료 처리가 끝났으면~
        // 이제 다시 데이터를 수신받기 위해서 수신 대기를 해야 합니다.
        // Begin~~ 메서드를 이용해 비동기적으로 작업을 대기했다면
        // 반드시 대리자 함수에서 End~~ 메서드를 이용해 비동기 작업이 끝났다고 알려줘야 합니다!
        ar.AsyncWaitHandle.WaitOne();
        Array.Clear(ao.Buffer, 0, ao.Buffer.Length);
        ao.WorkingSocket.BeginReceive(ao.Buffer, 0, ao.Buffer.Length, SocketFlags.None, _mFnReceiveHandler, ao);
        SendMessage("READ?");
    }
    catch (ObjectDisposedException)
    {
    }
    catch (SocketException)
    {
    }
}

private void HandleDataSend(IAsyncResult ar)
{

    // 넘겨진 추가 정보를 가져옵니다.
    var ao = (AsyncObject)ar.AsyncState;

    // 자료를 전송하고, 전송한 바이트를 가져옵니다.
    Int32 sentBytes = ao.WorkingSocket.EndSend(ar);

    if (sentBytes > 0)
        SetText(richTextBox1, "메세지 보냄: " + Encoding.UTF8.GetString(ao.Buffer));
}

private void Send_Click(object sender, EventArgs e)
{
    string message = richTextBox2.Text;
    SendMessage(message);
}


What I have tried:

i tried event handler and make thread inside of callback to quit server
and it is not work at all..
i think priority of event and listener and callback is problem.
i know listener is high-priority next callback last event
Posted
Updated 8-Aug-16 23:28pm

1 solution

try to dispose server and socket objects in close button.
also add

catch(Exception ex)
{
C#
MessageBox.Show(ex.Tostring);


}

// to catch if it throws any other unknown exceptions
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900