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

时间:2013-12-26 19:51:13

标签: c# sockets networking tcp

我这里有一个简单的客户端/服务器应用程序代码。 工作原理:客户输入“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);
        }
    }
}

我该如何解决这个问题?

1 个答案:

答案 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 - 它会让您的生活更轻松。

我还建议使用TcpClientTcpListener类来简化操作。它们是插座周围的包装纸。