我使用了codeguru中的代码并对其进行了修改,将必要的异步函数放在类中,以便从主程序中抽象出来。我之所以这样做是因为我们的主程序不仅仅是异步通信;它涉及数据库,但它不是我的项目工作范围。无论如何,来自站点的客户端和服务器的示例代码使用WinForms。在我的实现中,客户端在控制台中(因为它将作为微控制器在Raspberry Pi上运行),而服务器仍在WinForms(PC)中。
我无法让客户端接收数据。尽管说客户端和服务器没有连接但没有错误。
这是处理客户端异步功能的类。
// ClientSocket.cs
namespace Server.Networking
{
public class ClientSocket
{
byte[] _dataBuffer = new byte[10];
private IAsyncResult _result;
private AsyncCallback _pfnCallBack;
public Socket _clientSocket;
public string ipAddress; // = "192.168.1.101";
public int port; // = 151;
public string received = string.Empty;
public bool hasReceived = false;
public void ConnectToServer(string ipAddress, int port)
{
try
{
// Create the socket instance
_clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Create the remote IP address
IPAddress ip = IPAddress.Parse(ipAddress);
// Create the end point
IPEndPoint ipEnd = new IPEndPoint(ip, port);
// Connect to the remote host
_clientSocket.Connect(ipEnd);
if (_clientSocket.Connected)
{
//Wait for data asynchronously
WaitForData();
}
}
#region catch
catch (SocketException socketEx)
{
Console.WriteLine("Connection failed. Check if the server is running.\n\nError message: {0}", socketEx);
}
#endregion
}
public void SendMessage(string dataToSend)
{
try
{
byte[] byData = System.Text.Encoding.ASCII.GetBytes(dataToSend);
if (_clientSocket != null)
{
_clientSocket.Send(byData);
}
}
#region catch
catch (SocketException socketEx)
{
Console.WriteLine("Connection failed. Check if the server is running.\n\nError message: {0}", socketEx);
}
#endregion
}
public void WaitForData()
{
try
{
if (_pfnCallBack == null)
{
_pfnCallBack = new AsyncCallback(OnDataReceived);
}
SocketPacket theSocPkt = new SocketPacket();
theSocPkt.thisSocket = _clientSocket;
// Start listening to the data asynchronously
_result = _clientSocket.BeginReceive(theSocPkt.dataBuffer, 0, theSocPkt.dataBuffer.Length, SocketFlags.None, _pfnCallBack, theSocPkt);
}
#region catch
catch (SocketException socketEx)
{
Console.WriteLine("Connection failed. Check if the server is running.\n\nError message: {0}", socketEx);
}
#endregion
}
private void OnDataReceived(IAsyncResult asyn)
{
try
{
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
int iRx = theSockId.thisSocket.EndReceive(asyn);
char[] chars = new char[iRx + 1];
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
System.String szData = new System.String(chars);
hasReceived = true;
received = szData;
hasReceived = false;
WaitForData();
}
#region catch
catch (ObjectDisposedException objDispEx)
{
Console.WriteLine("Error messsage: {0}", objDispEx);
System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
}
catch (SocketException socketEx)
{
Console.WriteLine("Connection failed. Check if the server is running.\n\nError message: {0}", socketEx);
}
#endregion
}
public void DisconnectFromServer()
{
try
{
if (_clientSocket != null)
{
_clientSocket.Close();
_clientSocket = null;
}
}
#region catch
catch (Exception stopConEx)
{
Console.WriteLine("Error message: {0}", stopConEx);
}
#endregion
}
这是我的主要计划。
namespace Server
{
public static class Program
{
public static ClientSocket _client = new ClientSocket();
static void Main(string[] args)
{
_client.ipAddress = "192.168.1.101";
_client.port = 151;
string messageToSend = string.Empty;
Console.WriteLine("Connecting to server with IP Address {0} at port {1}.", _client.ipAddress, _client.port);
_client.ConnectToServer(_client.ipAddress, _client.port);
if (!_client._clientSocket.Connected)
{
Console.WriteLine("Cannot connect to server.");
}
else
{
try
{
while (_client._clientSocket.Connected)
{
if (_client.hasReceived)
Console.WriteLine("Message from server: {0}", _client.received);
}
}
#region catch
catch (Exception ex)
{
Console.WriteLine("Error message: {0}", ex);
}
#endregion
}
}
}
}
出于简化目的,我让客户端只接收数据,因为我遇到了发送问题。无论如何,这里是我在原始代码中实现的一些修改,当涉及到在客户端接收数据时。
ClientSocket.cs
中),对WaitForData()
没有“特殊”调用。通过'特殊'调用,我的意思是线程。运行它,客户端仍然无法接收数据。所以我尝试在类ClientSocket
中实现线程,但没有运气。使用Thread.isAlive
属性,在调试时,我已经看到线程停止,而我没有明确地在我的代码中说停止线程。当我尝试从服务器发送数据时,它会这样做。即使在我的主程序中进行线程化也行不通。public bool hasReceived
和public string received
。使用hasReceived
,我希望通知代码已在private void OnDataReceived(IAsyncResult asyn)
内,并且已收到数据。 received
存储收到的数据。到目前为止,hasReceived
仅因客户端程序未接收数据而返回false。 有了这些,您能看出为什么我的客户端程序没有接收数据吗?提前谢谢!