TCP Listener 和 Socket 的区别

Posted

技术标签:

【中文标题】TCP Listener 和 Socket 的区别【英文标题】:Difference between TCP Listener and Socket 【发布时间】:2012-09-03 22:10:20 【问题描述】:

据我所知,我可以同时使用 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); 
    

【问题讨论】:

【参考方案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 的代码的东西。它只是为了让你远离一些血腥的细节。

【讨论】:

以上是关于TCP Listener 和 Socket 的区别的主要内容,如果未能解决你的问题,请参考以下文章

基于TCP/IP协议的socket通讯server

socket,tcp,http三者之间的区别和原理

socket,tcp,http三者之间的区别和原理

tcpclient和socket的区别

TCP和UDP的区别(Socket)

域socket(domain socket)和ipsocket(TCP/IP socket)区别