gpt4 book ai didi

c# - AsyncCallback 没有被第二次调用

转载 作者:太空宇宙 更新时间:2023-11-04 11:54:45 25 4
gpt4 key购买 nike

我正在通过 tcp 实现乒乓球。我有用 C# 编写的 Pinger。还有两只火锅。一个用 C# 编写,另一个用 C++ 编写。 Pinger 只是向 pongers 发送消息,pongers 回复他。问题是,当 C# ponger 工作时,一切正常,但是当 C++ ponger 工作时,来自 Pinger 的行

 var res = client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);

不运行回调 (ReceiveCallback)。 ReceiveCallback 只被调用一次(从 Receive 函数)。pinger 代码片段在这里:

  private void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;

// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
} finally
{
}
}
private void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;

int bytesRead = 0;
try
{
// Read data from the remote device.
bytesRead = client.EndReceive(ar);
}
catch (ObjectDisposedException e)
{
Console.WriteLine(client.Connected);
if (_isDown)
return;
else
{
throw e;
}
}

if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

try
{
// Get the rest of the data.

var res = client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (ObjectDisposedException e)
{
if (_isDown)
return;
else
{
throw e;
}
}
}
else
{
// All the data has arrived; put it in _response.
if (state.sb.Length > 1)
{
_response = state.sb.ToString();
}
// Signal that all bytes have been received.
_receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}

C# Ponger 在这里:

  public void AsyncListenFor()
{
// Bind the socket to the local endpoint and listen for incoming connections.
while (_doPong)
{
try
{
_localEndPoint = new IPEndPoint(_ipAddress, _port);
if (!_listener.IsBound)
{
_listener = CreateSocket(_listener);
BindAndListen(_listener, _localEndPoint);
}
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
//Console.WriteLine("Waiting for a connection...");
_listener.Blocking = true;
_listener.BeginAccept(new AsyncCallback(AcceptCallback), _listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
catch (Exception e)
{
// здесь не будем показывать эксепшон WatchDog`у чтобы не перезагружать прогу
//(если автостартер не будет работать)
if (_listener != null)
{
try
{
//_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Socket dataSocket = AsyncSocket.EndAccept(_IAsyncResult);
_listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(false, 0));
_listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, false);
}
catch (Exception e2)
{ CLogger.WriteLog(CLogger.ELogLevel.DEBUG, e2.Message + "\n" + e2.StackTrace); }
try
{
_listener.Shutdown(SocketShutdown.Both);
}
catch (Exception e2)
{ CLogger.WriteLog(CLogger.ELogLevel.DEBUG, e2.Message + "\n" + e2.StackTrace); }
try
{
_listener.Disconnect(false);
}
catch (Exception e2)
{ CLogger.WriteLog(CLogger.ELogLevel.DEBUG, e2.Message + "\n" + e2.StackTrace); }
try
{
_listener.Close();
}
catch (Exception e2)
{ CLogger.WriteLog(CLogger.ELogLevel.DEBUG, e2.Message + "\n" + e2.StackTrace); }
}
CLogger.WriteLog(CLogger.ELogLevel.ERROR, "");
CLogger.WriteLog(CLogger.ELogLevel.DEBUG, e.Message + "\n" + e.StackTrace);
Thread.Sleep(1000);
}
}
}
public Socket CreateSocket(Socket listener)
{
if (listener != null)
{
try
{
listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(false, 0));
listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, false);
}
catch (Exception e2)
{ CLogger.WriteLog(CLogger.ELogLevel.DEBUG, e2.Message + "\n" + e2.StackTrace); }
try
{
_listener.Shutdown(SocketShutdown.Both);
}
catch (Exception e2)
{ CLogger.WriteLog(CLogger.ELogLevel.DEBUG, e2.Message + "\n" + e2.StackTrace); }
try
{
_listener.Disconnect(false);
}
catch (Exception e2)
{ CLogger.WriteLog(CLogger.ELogLevel.DEBUG, e2.Message + "\n" + e2.StackTrace); }
try
{
_listener.Close();
}
catch (Exception e2)
{ CLogger.WriteLog(CLogger.ELogLevel.DEBUG, e2.Message + "\n" + e2.StackTrace); }
}
try
{
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(false, 0));
listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, false);
} catch (Exception e)
{
CLogger.WriteLog(CLogger.ELogLevel.ERROR, "Не смогли создать сокет:\t" + e.Message);
}
return listener;
}
public void BindAndListen(Socket listener, IPEndPoint localEndPoint)
{
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
} catch (Exception e)
{ CLogger.WriteLog(CLogger.ELogLevel.DEBUG, e.Message + "\n" + e.StackTrace); }
}
public void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);

// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
public void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;

// Retrieve the state object and the handler socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;

// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);

if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.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)
{
// 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, _progName);
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
private void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);

// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
private void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;

// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
//Console.WriteLine("Sent {0} bytes to client.", bytesSent);

handler.Shutdown(SocketShutdown.Both);
handler.Close();

}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}

C++ Ponger 在这里:

// listen the sotket and send 
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
while(true) {
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
LOG(logINFO) << "Could not initialize Winsock";
continue;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Create a SOCKET for connecting to server
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET) {
LOG(logINFO) << "Could not create socket.";
WSACleanup();
continue;
}
// Setup the TCP listening socket
struct sockaddr_in client;
client.sin_family = AF_INET;
client.sin_port = htons(port_);
client.sin_addr.s_addr = inet_addr(ip_.c_str());
iResult = bind(ListenSocket, (struct sockaddr *)&client, sizeof(struct sockaddr_in));
if (iResult == SOCKET_ERROR) {
LOG(logINFO) << "Bind failed.";
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
continue;
}
iResult = listen(ListenSocket, 0);
if (iResult == SOCKET_ERROR) {
LOG(logINFO) << "listen failed";
closesocket(ListenSocket);
WSACleanup();
continue;
}
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
LOG(logINFO) << "accept failed";
closesocket(ListenSocket);
WSACleanup();
continue;
}
closesocket(ListenSocket);
// Receive until the peer shuts down the connection
do {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);

// Echo the buffer back to the sender
iSendResult = send( ClientSocket, recvbuf, iResult, 0 );
if (iSendResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
continue;
}
printf("Bytes sent: %d\n", iSendResult);
}
else if (iResult == 0)
printf("Connection closing...\n");
else {
LOG(logINFO) << "recv failed";
closesocket(ClientSocket);
WSACleanup();
continue;
}
} while (iResult > 0);
}

最佳答案

除非我遗漏了什么,否则在您的 C++ 服务器中您实际上并没有关闭客户端的套接字。

在 recv 返回 0 表示正常断开连接的情况下,我们进入 else if (iResult == 0) 分支。然后我们打印“Connection closing...”并退出 do ...while 循环。我们实际上没有在任何地方调用 shutdownclosesocket

您的程序也有一个非传统的结构。通常像这样的简单服务器看起来像:

create the listen socket
bind the listen socket
listen
while (!needToShutdown)
accept
read client request
do work
send response
shutdown client socket
close client socket
// we are now shutting down
close listen socket

请注意,这里我们在接受客户端后不会关闭监听套接字。我们可以使用同一个监听套接字一个接一个地接受多个客户端。 Wikipedia有一个例子。 (让这个服务同时处理多个客户端太复杂了,无法在这里讨论。)

关于c# - AsyncCallback 没有被第二次调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16612047/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com