套接字编程 - 简单的客户端/服务器应用程序 [英] Socket Programming - Simple Client/Server Application

查看:45
本文介绍了套接字编程 - 简单的客户端/服务器应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

问题是客户端成功连接服务器后抛出NullReferenceException.为什么会这样?

代码:

客户:

使用系统;使用 System.Collections.Generic;使用 System.Linq;使用 System.Text;使用 System.Net;使用 System.Net.Sockets;命名空间 Time_Client{课程计划{私有静态 Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);static void Main(string[] args){Console.Title = "客户端";循环连接();发送循环();Console.ReadLine();}私有静态无效 SendLoop(){而(真){Console.Write("输入请求:");string req = Console.ReadLine();byte[] buffer = Encoding.ASCII.GetBytes(req);clientSocket.Send(buffer);byte[] receivedBuf = 新字节 [1024];int rec = clientSocket.Receive(receivedBuf);字节 [] 数据 = 新字节 [rec];Array.Copy(receivedBuf, data, rec);Console.WriteLine("收到:" + Encoding.ASCII.GetString(data));}}私有静态无效 LoopConnect(){int 尝试 = 0;while (!clientSocket.Connected){尝试{尝试++;clientSocket.Connect(IPAddress.Loopback, 100);}捕获(套接字异常){Console.WriteLine("连接尝试次数:" + 尝试次数);}}Console.Clear();Console.WriteLine("已连接");}}}

服务器:

使用系统;使用 System.Collections.Generic;使用 System.Linq;使用 System.Text;使用 System.Threading.Tasks;使用 System.Net;使用 System.Net.Sockets;命名空间 Time_Server{课程计划{私有静态字节[]缓冲区=新字节[1024];私有静态列表<套接字>clientSockets = new List();私有静态 Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);static void Main(string[] args){Console.Title = "服务器";设置服务器();Console.ReadLine();}私有静态无效 SetupServer(){Console.WriteLine("正在设置服务器...");serverSocket.Bind(new IPEndPoint(IPAddress.Any, 100));serverSocket.Listen(5);serverSocket.BeginAccept(new AsyncCallback(RecieveCallback), null);}私有静态无效 AcceptCallback(IAsyncResult AR){套接字套接字 = serverSocket.EndAccept(AR);clientSockets.Add(socket);Console.WriteLine("客户端连接");socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(RecieveCallback), socket);serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);}私有静态无效接收回调(IAsyncResult AR){Socket socket = (Socket)AR.AsyncState;int 接收 = socket.EndReceive(AR);//这里抛出异常字节[] dataBuf = 新字节[接收];Array.Copy(buffer, dataBuf, 收到);字符串文本 = Encoding.ASCII.GetString(dataBuf);Console.WriteLine("收到的文本:" + text);字符串响应 = "";if (text.ToLower() != "get time"){response = "无效请求";}别的{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);}私有静态无效 SendCallback(IAsyncResult AR){Socket socket = (Socket)AR.AsyncState;socket.EndSend(AR);}}}

我该如何解决这个问题?

解决方案

啊,我搞错了什么.这就是问题所在.

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 类使事情变得更简单.它们是套接字周围的包装器.

I've have this code here of a simple Client/Server application. How it works: The client enters "get time", and the server responds with the time.

The problem is that a NullReferenceException is thrown after the client successfully connects to the server. Why does that happen?

Codes:

Client:

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");
        }
    }
}

Server:

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);
        }
    }
}

How can I solve this?

解决方案

EDIT: Ah, I was mistaken in what was wrong. This is the problem.

serverSocket.BeginAccept(new AsyncCallback(RecieveCallback), null);

Note that you're using RecieveCallback instead of AcceptCallback. So you end up in RecieveCallback (which should be ReceiveCallback, by the way) at which point you find the async state - which is null - and call EndReceive... but this isn't the callback for Receive operation, it's a callback for an Accept operation.

The line above should be:

serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);

However, if you're trying to write a simple client/server program, I would avoid using async IO at all, and just go for synchronous operations, to start with. When you do want to use asynchronous operations, use async / await from C# 5 - it'll make your life a lot easier.

I'd also recommend using the TcpClient and TcpListener classes to make things simpler. They're wrappers around the sockets.

这篇关于套接字编程 - 简单的客户端/服务器应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆