44

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

TCP监听器

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

4 回答 4

40

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

TcpClient.GetStream返回一个NetworkStream适合的对象SslStream;所以,它应该比Socket直接使用要少得多。SslStream的文档详细说明了使用SSL 通信TcpListenerTcpClient用于 SSL 通信。

于 2012-09-12T00:45:51.070 回答
24

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

于 2012-09-11T02:34:32.643 回答
18

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

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

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

于 2012-09-11T02:36:43.170 回答
-1

我并没有真正回答这个问题,但您似乎更喜欢它,TcpClient因为它GetStream()可以与 a 一起使用SslStream,但您可以通过将NetworkStreama作为构造函数传递给SocketSocketNetworkStream

IENetworkStream myStream = new NetworkStream(mySocket);

于 2016-02-28T17:25:15.123 回答