41

As far as I know I can create a server using both TCPListener and Socket, so what is the difference between the two of them?

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

I'm really confused. The two of them listen for connections, so what is the difference between them?

Updated Code

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); }
    }
}
Andrew Brooke
  • 11,633
  • 8
  • 32
  • 53
Roman Ratskey
  • 4,609
  • 6
  • 40
  • 66

4 Answers4

38

TcpListener is a convenient wrapper for TCP communications. This allows you to use TcpClient for accepted connections--although you can accept sockets instead of clients to use Socket instead of TcpClient. You can do the same thing with Socket; but you have to deal with some of the TCP-specifics (like SocketType.Stream, ProtocolType.Tcp). TCP is a stream-based protocol and TcpClient recognizes that by letting you do stream communications by providing a stream with TcpClient.GetStream(). Socket is at a higher different level and needs to support many different protocols like UDP that aren't stream based.

TcpClient.GetStream returns a NetworkStream object that is suitable for SslStream; so, it should be much less work than using Socket directly. The documentation for SslStream details using TcpListener and TcpClient for SSL communications.

Peter Ritchie
  • 33,368
  • 9
  • 74
  • 96
23

They're just different classes that do the same thing, written at different levels. Under the hood the TCPListener undoubtedly calls something very like your first Socket-based code. It;s just there to hide you from some of the gory details.

user207421
  • 289,834
  • 37
  • 266
  • 440
18

A TcpListener wraps a socket, and is the server-side analog to the TcpClient (which also, of course, wraps a socket).

The TcpListener is preconfigured with TCP (as opposed to the Socket, which can be used with UDP, pure IP, non-IP protocols, etc.) and gives you a TcpClient when handling a connection.

If you're not sure if you need a Socket, and are using TCP - I'd strongly suggest starting with TcpListener/Client as it's a much easier to use interface.

Mark Brackett
  • 81,638
  • 17
  • 102
  • 150
  • I want to use SSL Stream but idk how could i use .GetStream with the socket class [First Example] – Roman Ratskey Sep 11 '12 at 14:30
  • @TorlanOther - first, you need a stream on top of the socket: System.Net.NetworkStream will give you that. Then, construct an SslStream on top of the NetworkStream. – Mark Brackett Sep 11 '12 at 14:56
  • so you mean on the AcceptConnections Callback i make a network stream that gets the stream from the AsyncResult, then i use .GetStream with SSLStream ? – Roman Ratskey Sep 11 '12 at 15:30
  • see my updated code i now can accept connections and authenticate with SSL stream after edited my code as you told me but still can't receive data so please help me – Roman Ratskey Sep 11 '12 at 22:46
  • @TorlanOther - I don't see anywhere you're actually reading from the stream. I presume that's in the unshown event handlers? – Mark Brackett Sep 13 '12 at 16:06
  • @Timeless - in general, performance of a well-known higher-level abstraction is going to be equivalent or better than naively reimplementing the same abstraction. So the Q is really - do I want (and can afford) this abstraction. The rest is a question best suited for a profiler.... – Mark Brackett Nov 07 '17 at 09:34
-1

I'm not really answering the question, but you seem to like TcpClient better because it has GetStream() which you can use with an SslStream, but you can get a NetworkStream out of a Socket by passing the Socket as a constructor to NetworkStream

i.e. NetworkStream myStream = new NetworkStream(mySocket);

robbie
  • 1,075
  • 1
  • 10
  • 18