C# 套接字编程-简单的客户端/服务器应用程序

C# 套接字编程-简单的客户端/服务器应用程序,c#,sockets,networking,tcp,C#,Sockets,Networking,Tcp,我这里有一个简单的客户机/服务器应用程序的代码。 工作原理:客户端输入“获取时间”,服务器响应时间 问题在于,客户机成功连接到服务器后会引发NullReferenceException。为什么会这样 代码: 客户: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; namespace T

我这里有一个简单的客户机/服务器应用程序的代码。 工作原理:客户端输入“获取时间”,服务器响应时间

问题在于,客户机成功连接到服务器后会引发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);
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
Net系统;
使用System.Net.Sockets;
命名空间时间服务器
{
班级计划
{
专用静态字节[]缓冲区=新字节[1024];
private static List clientSockets=new List();
私有静态套接字serverSocket=新套接字(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
静态void Main(字符串[]参数)
{
Console.Title=“服务器”;
SetupServer();
Console.ReadLine();
}
私有静态void SetupServer()
{
Console.WriteLine(“设置服务器…”);
Bind(新的IPEndPoint(IPAddress.Any,100));
serverSocket.Listen(5);
serverSocket.BeginAccept(新的AsyncCallback(ReceiveCallback),null);
}
私有静态void AcceptCallback(IAsyncResult AR)
{
套接字=serverSocket.EndAccept(AR);
clientSockets.Add(socket);
Console.WriteLine(“客户端连接”);
socket.BeginReceive(缓冲区,0,缓冲区.Length,SocketFlags.None,新异步回调(ReceiveCallback),套接字);
serverSocket.BeginAccept(新的AsyncCallback(AcceptCallback),null);
}
私有静态void receiveCallback(IAsyncResult AR)
{
套接字套接字=(套接字)AR.AsyncState;
int received=socket.EndReceive(AR);//在这里抛出异常
byte[]dataBuf=新字节[已接收];
复制(缓冲区、数据缓冲区、接收);
字符串文本=Encoding.ASCII.GetString(dataBuf);
Console.WriteLine(“接收到的文本:+Text”);
字符串响应=”;
if(text.ToLower()!=“获取时间”)
{
response=“无效请求”;
}
其他的
{
response=DateTime.Now.ToLongTimeString();
}
字节[]数据=Encoding.ASCII.GetBytes(响应);
socket.BeginSend(数据,0,数据.Length,SocketFlags.None,新异步回调(ReceiveCallback),套接字);
socket.BeginReceive(缓冲区,0,缓冲区.Length,SocketFlags.None,新异步回调(ReceiveCallback),套接字);
}
私有静态void SendCallback(IAsyncResult AR)
{
套接字套接字=(套接字)AR.AsyncState;
socket.EndSend(AR);
}
}
}

我怎样才能解决这个问题呢?

编辑:啊,我错在哪里了。这就是问题所在

serverSocket.BeginAccept(new AsyncCallback(RecieveCallback), null);
请注意,您使用的是
receivecallback
而不是
AcceptCallback
。因此,您最终将进入
ReceiveCallback
(顺便说一下,它应该是
ReceiveCallback
),此时您将找到异步状态(为null)并调用
EndReceive
。。。但这不是对
Receive
操作的回调,而是对
Accept
操作的回调

上面的行应该是:

serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
然而,如果您试图编写一个简单的客户机/服务器程序,我将完全避免使用异步IO,而只是从同步操作开始。如果您确实想使用异步操作,请使用C#5中的
async
/
wait
——这将使您的生活更加轻松


我还建议使用和类使事情更简单。它们是围绕套接字的包装器。

引发异常的地方是客户端还是服务器?(您是否考虑过使用
TcpClient
TcpListener
?)在服务器上引发异常。老实说,我从YouTube视频上复制了这段代码(因为我是新手),但出于某种原因,它在YouTube视频上起作用,但在这里不起作用。问题是什么?考虑到我在回答中发现的问题,我非常怀疑代码是否能正常工作。。。(在使用静态变量等方面,它也不是很好的代码。我认为如果可以的话,最好在MSDN上查找示例。)谢谢,但现在它抛出了一个新的异常:“IAsyncResult对象不是从该类上相应的异步方法返回的。参数名称:asyncResult”@蓝光010:啊-你的回叫也错了。好的,谢谢。按照你说的编辑代码,但是现在有一个小问题。例如,当我说“获取时间”时,它会在服务器中多次写入“文本接收”,而不是一次。当我输入一个无效请求时,它会在客户端写入大量“无效请求”,而不是一次。我怎样才能解决这个问题?@BlueRay010:这些听起来像是不同的问题。堆栈溢出真的不是处理这类事情的好方法,因为你从一堆你不太理解的代码开始——如果只有一个明显的问题,它会更好。我建议你花些时间解决问题,尽可能地诊断它们,然后在必要时问一个新问题。我还强烈建议使用同步代码,除非练习的重点是学习异步套接字编程。如果能同步地看到正在发生的事情会简单得多。我知道,我正在努力学习,但我真的不明白为什么会发生这种情况。例如,写这么多次“无效请求”的原因是什么?我在努力学习,这是其中的一部分。那为什么不一次呢?问题出在哪里?