Reputation: 554
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.
Upvotes: 2
Views: 8571
Reputation: 70652
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/
Upvotes: 4