【问题标题】:Difference between TCP Listener and SocketTCP Listener 和 Socket 的区别
【发布时间】:2025-12-19 01:35:15
【问题描述】:

据我所知,我可以同时使用 TCPListener 和 Socket 创建服务器,那么它们两者有什么区别?

套接字

private Socket MainSock;
MainSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
MainSock.Bind(new IPEndPoint(IPAddress.Any, port));
MainSock.Listen(500);
MainSock.BeginAccept(AcceptConnections, new Wrapper());

TCPListener

    Int32 port = 13000;
    IPAddress localAddr = IPAddress.Parse("127.0.0.1");
    TcpListener server = new TcpListener(localAddr, port);
    server.Start();

我真的很困惑。他们两个监听连接,那么他们有什么区别呢?

更新代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.IO;

public class Wrapper
{
    public byte[] buffer;
    public SslStream sslStream;
    public object connector;
}

public class Sock
{
    private Dictionary<string, byte> Connections;
    public event Action<Wrapper> AnnounceNewConnection;
    public event Action<Wrapper> AnnounceDisconnection;
    public event Action<byte[], Wrapper> AnnounceReceive;
    private Socket _sock;

    private X509Certificate certificate = X509Certificate.CreateFromCertFile("exportedcertificate.cer");

    public Sock(int port)
    {
        try
        {
            Connections = new Dictionary<string, byte>();
            _sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _sock.Bind(new IPEndPoint(IPAddress.Any, port));
            _sock.Listen(500);
            _sock.BeginAccept(AcceptConnections, new Wrapper());
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }

    private void AcceptConnections(IAsyncResult result)
    {
        Wrapper wr = (Wrapper)result.AsyncState;
        try
        {
            wr.sslStream = new SslStream(new NetworkStream(_sock.EndAccept(result), true));
            wr.sslStream.BeginAuthenticateAsServer(certificate, AcceptAuthenticate, wr);

            _sock.BeginAccept(AcceptConnections, new Wrapper());
        }
        catch (Exception e) { Console.WriteLine(e); }
    }

    private void AcceptAuthenticate(IAsyncResult result)
    {
        Wrapper wr = (Wrapper)result.AsyncState;
        try
        {
            wr.sslStream.EndAuthenticateAsServer(result);
            if (wr.sslStream.IsAuthenticated == true)
            {
                AnnounceNewConnection.Invoke(wr);
            }
        }
        catch (Exception e) { Console.WriteLine(e); }
    }

    private void ReceiveData(IAsyncResult result)
    {
        Wrapper wr = (Wrapper)result.AsyncState;
        try
        {
            AnnounceReceive.Invoke(wr.buffer, wr);
        }
        catch (Exception e) { Console.WriteLine(e); AnnounceDisconnection.Invoke(wr); }
    }
}

【问题讨论】:

    标签: sockets tcp client serversocket tcplistener


    【解决方案1】:

    我并没有真正回答这个问题,但您似乎更喜欢TcpClient,因为它有GetStream(),您可以将其与SslStream 一起使用,但您可以从@987654325 中获得NetworkStream @ 通过将Socket 作为构造函数传递给NetworkStream

    NetworkStream myStream = new NetworkStream(mySocket);

    【讨论】:

    • 我不记得写这个了。
    【解决方案2】:

    TcpListener 是一个方便的 TCP 通信包装器。这允许您使用TcpClient 来接受连接——尽管您可以接受套接字而不是客户端来使用Socket 而不是TcpClient。你可以用Socket 做同样的事情;但是您必须处理一些 TCP 细节(例如 SocketType.Stream, ProtocolType.Tcp)。 TCP 是一种基于流的协议,TcpClient 认识到这一点,通过提供带有TcpClient.GetStream() 的流,您可以进行流通信。 Socket 处于更高不同的级别,需要支持许多不同的协议,例如不基于流的 UDP。

    TcpClient.GetStream返回一个适合SslStreamNetworkStream对象;所以,它应该比直接使用Socket 少得多。 documentation for SslStream 详细说明使用 TcpListenerTcpClient 进行 SSL 通信。

    【讨论】:

    • 在我的异步套接字类中,我曾经使用 socket.BeginReceive 开始接收从客户端发送的每条消息。但是现在在我用 sslstream 包装我的套接字类以保护连接 idk 之后,什么相当于 .BeginReceive in ssl
    • 所以我希望你能帮助我在主帖中更新我上面的代码
    • @TorlanOther 如果你使用的是SslStream,你会想使用SslStream.BeginRead
    • 每次我尝试在上面的代码上使用它时,我都没有得到任何数据,为什么你能看到我的代码,因为我真的需要你的帮助,我很困惑为什么它不起作用
    • 我没有收到消息只有我收到一条空消息,1000+++ 个空格
    【解决方案3】:

    TcpListener 包装了一个套接字,并且是 TcpClient 的服务器端模拟(当然,它也包装了一个套接字)。

    TcpListener 预配置了 TCP(与 Socket 不同,它可以与 UDP、纯 IP、非 IP 协议等一起使用)并在处理连接时为您提供 TcpClient。

    如果您不确定是否需要 Socket,并且正在使用 TCP - 我强烈建议您从 TcpListener/Client 开始,因为它是一个更易于使用的接口。

    【讨论】:

    • 我想使用 SSL Stream 但我不知道如何将 .GetStream 与套接字类一起使用 [第一个示例]
    • @TorlanOther - 首先,您需要在套接字顶部有一个流:System.Net.NetworkStream 将为您提供。然后,在 NetworkStream 之上构建一个 SslStream。
    • 所以你的意思是在 AcceptConnections 回调中我创建了一个从 AsyncResult 获取流的网络流,然后我将 .GetStream 与 SSLStream 一起使用?
    • 查看我更新的代码,我现在可以接受连接并在按照您告诉我的编辑代码后使用 SSL 流进行身份验证,但仍然无法接收数据,所以请帮助我
    • @TorlanOther - 我看不到您实际从流中读取的任何地方。我想那是在未显示的事件处理程序中?
    【解决方案4】:

    它们只是做同样事情的不同类,写在不同的层次上。在底层,TCPListener 无疑调用了一些非常类似于您的第一个基于 Socket 的代码的东西。它只是为了让你远离一些血腥的细节。

    【讨论】: