据我所知,我可以同时使用 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); }
}
}
TcpListener
是 TCP 通信的便捷包装器。这允许您使用 TcpClient
来接受连接——尽管您可以接受套接字而不是客户端来使用 Socket
而不是 TcpClient
。你可以用 Socket
做同样的事情;但你必须处理一些 TCP 特定的问题(比如 SocketType.Stream, ProtocolType.Tcp
)。 TCP 是基于流的协议,TcpClient
认识到这一点,让您通过提供带有 TcpClient.GetStream()
的流来进行流通信。 Socket
处于TcpClient.GetStream
返回适合 NetworkStream
的 SslStream
对象;所以,它应该比直接使用 Socket
少很多工作。 SslStream 文档详细介绍了如何使用 TcpListener
和 TcpClient
进行 SSL 通信。
它们只是做同样事情的不同类,在不同级别编写。在底层,TCPListener 无疑会调用与您的第一个基于 Socket 的代码非常相似的东西。它只是为了让您隐藏一些血淋淋的细节。
A TcpListener 包装了一个套接字,并且是 TcpClient 的服务器端模拟(当然,它也包装了一个套接字)。
TcpListener 预先配置了 TCP(与 Socket 不同,Socket 可以与 UDP、纯 IP、非 IP 协议等一起使用),并在处理连接时为您提供 TcpClient。
如果您不确定是否需要 Socket,并且正在使用 TCP - 我强烈建议从 TcpListener/Client 开始,因为它是一个更容易使用的接口。
我并没有真正回答这个问题,但你似乎更喜欢
TcpClient
,因为它有GetStream()
,你可以将其与SslStream
一起使用,但你可以通过以下方式从NetworkStream
中得到Socket
将 Socket
作为构造函数传递给 NetworkStream
即
NetworkStream myStream = new NetworkStream(mySocket);