我想在收到回电时按钮事件 [英] I want to button event when callback received
问题描述
在我的代码中,soket收到了异步。并且在接收回调中有发送消息。
所以回调总是循环。
收到发送收到的发送.......
在这种情况下如何我可以打断这个循环并退出。
i make quit按钮但不起作用。只有我快点击很多次。
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.
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);
}
我的尝试:
i尝试了事件处理程序并在回调中使线程退出服务器
并且根本不起作用..
i认为事件和监听器的优先级和回调是问题。
i know listener是高优先级的下一个回调最后一个事件
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
推荐答案
尝试在关闭按钮中配置服务器和套接字对象。
还添加
catch(例外情况)
{
try to dispose server and socket objects in close button.
also add
catch(Exception ex)
{
MessageBox.Show(ex.Tostring);
}
//如果它引发任何其他未知异常,则捕获
}
// to catch if it throws any other unknown exceptions
这篇关于我想在收到回电时按钮事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!