Search code examples
c#socketstcptcpclientraw-sockets

Creating TCP connection and getting the Header


Im making an application that needs to receive a TCP connection that comes with a request that contains some header data that i need to read and send back with more info later. The issue is that after googling everywhere for days and countless tests it seems the only way to get the Header from a TCP connection is with using sockets specifically Raw sockets and enabling "SocketOptionName.HeaderIncluded" But when using raw sockets i cant find a way to make a stable TCP connection. Only two ways i seem to be able to make a connection is with normal TCP client and with normal sockets (example)`

    private static readonly Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
    private const int BUFFER_SIZE = 2048;
    private const int PORT = 52000;
    private static readonly byte[] buffer = new byte[BUFFER_SIZE];
    private static readonly List<Socket> clientSockets = new List<Socket>();

    public static void ServerMode()
    {
        Console.WriteLine("Setting up server...");
        serverSocket.Bind(new IPEndPoint(IPAddress.Any, PORT));
        serverSocket.Listen(0);
        serverSocket.BeginAccept(AcceptCallback, null);
        Console.WriteLine("Server setup complete");
        while (true) { Thread.Sleep(10); }
    }


    private static void AcceptCallback(IAsyncResult AR)
    {
        Socket socket;

        try
        {
            socket = serverSocket.EndAccept(AR);
        }
        catch (ObjectDisposedException) 
        {
            return;
        }

        clientSockets.Add(socket);
        socket.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCallback, socket);
        Console.WriteLine("Client connected, waiting for request...");
        serverSocket.BeginAccept(AcceptCallback, null);
    }

    private static void ReceiveCallback(IAsyncResult AR)
    {
        Socket current = (Socket)AR.AsyncState;
        int received;

        try
        {
            received = current.EndReceive(AR);
        }
        catch (SocketException)
        {
            Console.WriteLine("Client forcefully disconnected");
            // Don't shutdown because the socket may be disposed and its disconnected anyway.
            current.Close();
            clientSockets.Remove(current);
            return;
        }

        byte[] recBuf = new byte[received];
        Array.Copy(buffer, recBuf, received);
        string text = Encoding.ASCII.GetString(recBuf);
        Console.WriteLine("Received Text: " + text);

        current.BeginReceive(buffer, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
    }

`But when running Raw your cant use socket.Listen(); Im hoping someone has experienced anything like this and has a solution, either a way to establish a TCP connection with raw sockets or a way to get the header from a TCP connection. Im constantly baffled by how hard it is to get the god damm header.


Solution

  • ... that comes with a request that contains some header ...

    You are mixing things up here: TCP has no requests, TCP is only an unstructured stream of bytes. Any semantic of "message", "request" or similar is purely at the application level, i.e. an application protocol which defines a structure semantic on top of the unstructured byte stream. An example for such an application protocol is HTTP which defines a message as having a variable sized header and body and the notion of request and response as specific kinds of messages.

    ... it seems the only way to get the Header from a TCP connection is with using sockets specifically Raw sockets and enabling "SocketOptionName.HeaderIncluded"

    Based on your last question you are not actually looking for a TCP header, but for an application message which contains some header. To cite:

    ... how to get the TCP header in c#. I know that the messages that I will receive will include two headers, a 16 - byte header and a 48 - byte header.

    Given that the TCP header is always 20 bytes you cannot mean the real TCP header here, but this is about some kind of message header for some unknown kind of message format. No raw sockets are needed in this case, but you simple need to read as much bytes as the message/request has and then strip the header from what you've read.

    But how much bytes you need read for the request and how to strip the header from the request fully depends on the application protocol. If there is always some first header with 16 bytes, then read 16 bytes from the socket. If there is always another header with 48 bytes read these 48 byte. If these header somehow define how large the rest of the message is, extract this information and read that much bytes.

    So the first information you need is to find out, how exactly the protocol is defined, i.e. how the structure of a message or requests is mapped to a stream of bytes. Without this information it is impossible to implement your task.