2

I'm trying to use a socket (System.Net.Socket, even tried TcpListener/Client/Etc.) to be able to listen for data, while it's waiting to or already sending data.

I've done the following:

    public byte[] bytesIn;
    public byte[] bytesOut;
    public Socket transmitter;
    public Socket receiver;

    public Comlink(String ipAddress, int portNum) 
    {

        try
        {
            IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(ipAddress), 11000);

            transmitter = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            transmitter.Listen(10);

            receiver = transmitter.Accept();
            receiver.Receive(bytesIn);

            try
            {
                transmitter.Connect(remoteEP);
                this.bytesOut = Encoding.ASCII.GetBytes("<SYNCUP>");
                int bytesSent = transmitter.Send(this.bytesOut);
                this.connected = true;
            }
        }  // (Omitted my exception handling.)
    }

The Receive() function:

this.bytesIn = new byte[1024];
Socket receiver = transmitter.Accept();
int bytesReceived = receiver.Receive(this.bytesIn);

Code that binds it:

while(comlink.connected)
{
    comlink.Receive();
    handlePacket(comlink.bytesIn);
}

I'm just not entirely sure if I'm using the right process to receive data, as that's always been the complaint from .NET. I need data to be handled as it comes in.

Something like a two-way street: Data can freely come in (without the program having to move back to Receive() and wait for the data), it gets handled. Data can move freely from the client and to the server, as well. I know TCP sockets are bidirectional, but I need to improve this class so that I can enjoy the full benefits of having a free, open road.

1 Answer 1

4

There are at least two things wrong with just the code you show. First, your socket should be used to listen, or to connect to a remote socket, but not both. Frankly, I'm surprised .NET doesn't throw an exception when code tries to call Connect() after it's already been put into listening mode.

Second, you only need to accept a connection once. Accepting before each call to Receive() is wrong and will cause your code to only receive the first buffer's worth of data from each socket that is connected to it.

In general, your Socket-based implementation will require a "server" and a "client". Note that once the connection is established, the roles do not need to remain so firmly established. But it's critical that they are at the start.

The server will create a new "listening" socket. With this socket, it will "accept" connection requests from clients, a process which will create a new socket that is actually used for communication.

I reiterate: the server's original socket is never used for actually communicating over a connection. It's simply the socket that's used to create connections.

The client will create a single socket. With this socket, it will attempt to "connect" to the server's socket. Once the connection is established, that same socket is then used for the actual communication.

As you note, TCP connections are bidirectional. So once the connection is established, the server and client can each use their single socket for the connection to both send and receive data. Noting, of course, that in single-threaded code you can't do both at the same time. So either your high-level protocol needs to be a call-and-response style protocol where each end knows precisely when it needs to either send or receive data, and it never needs to do both at the same time, or you need to use one of the asynchronous APIs .NET provides for Sockets, so that you can handle sending and receiving at the same time.

MSDN has reasonably decent Socket programming examples. You should start there.

A long time ago (in Internet years anyway :) ), I wrote a series of blog posts to try to help people get started in .NET Socket programming. It's one of the few things I ever wound up finding the time to write; you might consider checking it out in case it is helpful to you: http://blogs.msmvps.com/duniho/2008/08/19/basic-network-programming-in-net/

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks. I was thinking it over today and I thought "wait, why was I trying to accept connections on that socket? They're already bi-directional!", thinking this was my eureka moment. But it wasn't, since, as you explained, you can't send and receive data simultaneously. I was afraid of Async socket programming but now I realize why they exist.
You can use a single socket for listening and then communicating, but you would only do this if a single server-client connection was needed.
I believe you can communicate both ways simultaneously on the socket using threads without using asynch too, but of course that would waste threads.
@Bent: "You can use a single socket for listening and then communicating" -- that is incorrect. The socket implementation of the TCP protocol requires the actual communication socket to be returned from the accept method of the listening socket; the two are mutually exclusive. As for bidirectional communication without the async API, well...of course, since there are synchronous methods on the socket, naturally it can be done without async. Whether additional threads are used depends on the exact implementation and performance requirements.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.