我这里有一个简单的客户端/服务器应用程序代码。 工作原理:客户输入“get time”,服务器响应时间。
问题是在客户端成功连接到服务器后抛出NullReferenceException。为什么会这样?
代码:
客户端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace Time_Client
{
class Program
{
private static Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
static void Main(string[] args)
{
Console.Title = "Client";
LoopConnect();
SendLoop();
Console.ReadLine();
}
private static void SendLoop()
{
while (true)
{
Console.Write("Enter a request: ");
string req = Console.ReadLine();
byte[] buffer = Encoding.ASCII.GetBytes(req);
clientSocket.Send(buffer);
byte[] receivedBuf = new byte[1024];
int rec = clientSocket.Receive(receivedBuf);
byte[] data = new byte[rec];
Array.Copy(receivedBuf, data, rec);
Console.WriteLine("Received: " + Encoding.ASCII.GetString(data));
}
}
private static void LoopConnect()
{
int attempts = 0;
while (!clientSocket.Connected)
{
try
{
attempts++;
clientSocket.Connect(IPAddress.Loopback, 100);
}
catch (SocketException)
{
Console.WriteLine("Connection attempts: " + attempts);
}
}
Console.Clear();
Console.WriteLine("Connected");
}
}
}
服务器:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace Time_Server
{
class Program
{
private static byte[] buffer = new byte[1024];
private static List<Socket> clientSockets = new List<Socket>();
private static Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
static void Main(string[] args)
{
Console.Title = "Server";
SetupServer();
Console.ReadLine();
}
private static void SetupServer()
{
Console.WriteLine("Setting up server...");
serverSocket.Bind(new IPEndPoint(IPAddress.Any, 100));
serverSocket.Listen(5);
serverSocket.BeginAccept(new AsyncCallback(RecieveCallback), null);
}
private static void AcceptCallback(IAsyncResult AR)
{
Socket socket = serverSocket.EndAccept(AR);
clientSockets.Add(socket);
Console.WriteLine("Client Connected");
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(RecieveCallback), socket);
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
private static void RecieveCallback(IAsyncResult AR)
{
Socket socket = (Socket)AR.AsyncState;
int received = socket.EndReceive(AR); // the exception is thrown here
byte[] dataBuf = new byte[received];
Array.Copy(buffer, dataBuf, received);
string text = Encoding.ASCII.GetString(dataBuf);
Console.WriteLine("Text received: " + text);
string response = "";
if (text.ToLower() != "get time")
{
response = "Invalid Request";
}
else
{
response = DateTime.Now.ToLongTimeString();
}
byte[] data = Encoding.ASCII.GetBytes(response);
socket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(RecieveCallback), socket);
socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(RecieveCallback), socket);
}
private static void SendCallback(IAsyncResult AR)
{
Socket socket = (Socket)AR.AsyncState;
socket.EndSend(AR);
}
}
}
我该如何解决这个问题?
答案 0 :(得分:0)
serverSocket.BeginAccept(new AsyncCallback(RecieveCallback), null);
请注意,您使用的是RecieveCallback
而不是AcceptCallback
。所以你最终进入RecieveCallback
(顺便说一句,这应该是ReceiveCallback
),此时你会发现异步状态 - 这是空的 - 并且调用EndReceive
......但这不是不是Receive
操作的回调,它是Accept
操作的回调。
上面的行应该是:
serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
但是,如果您正在尝试编写简单客户端/服务器程序,我将完全避免使用异步IO,而只是开始执行同步操作。当做想要使用异步操作时,使用C#5中的async
/ await
- 它会让您的生活更轻松。
我还建议使用TcpClient
和TcpListener
类来简化操作。它们是插座周围的包装纸。