2

I want to design a TCP server which listens for x clients. X is small, say around 10 and its fixed. Clients may connect at any time. Once the connection is established (accept() successful) I spawn a thread for each client and handle them.

In this handle() function I want to send commands to client and receive the data accordingly.

Problem: Once a command has been sent from the server the client responds by sending data continuously. How do I send a command back to the client to stop it? As with the current code I'm in a loop receiving data from the client.

  1. I don't know how to send the command from server thread while receive is in progress, like should I need to have another thread (to send cmds) once the connection is established?
  2. How to continuously receive data from clients and also send commands at the same time? Sending commands to each client based on user inputs. (Say user wants client1 to start sending data, then I have to send START to client1. And user wants to stop the client1 from sending, so I need to send STOP to client1 And if user wants data3 cmd to be sent to client 4 then send command DATA3 to client4 etc. How do identify the client in this case? Basically forming a small protocol**

The below code is working where I can listen on socket and client connects and sends data. I'm not sure of how to send user inputted commands to the right client (say client4) and also receive at same time.

m4n07
  • 2,267
  • 12
  • 50
  • 65
  • Can you provide a more insight into what application are you trying tp create. From your post its not obvious what you are trying to achieve. – Pradheep Feb 25 '13 at 17:42
  • @pradheep, I would like to transfer data from few of my devices to a server based on my commands. since my devices continuously generate data, I need to communicate them saying START SENDING,END,GETTHISDATA, some times i also need to continuously get data for weeks,some for 5 min etc. – m4n07 Feb 25 '13 at 17:49

4 Answers4

1

If you want to really continously stream data and in parallel want to exchange commands you won't get around an addtional connection to establish the command channel. The alternativ would be some kind of multiplexing. Stream a chunk of data, check for commands, stream the next chunk, check for commands again ... - complicated and error prone as the stream is continously interupted ...

The stone old ftp protocol does something similar: http://en.wikipedia.org/wiki/Ftp and https://www.rfc-editor.org/rfc/rfc959 (see ascii art in chapter 2.3)

Community
  • 1
  • 1
alk
  • 69,737
  • 10
  • 105
  • 255
  • Thanks. But FTP doesn't wait for any commands once it starts to send data to server. – m4n07 Feb 25 '13 at 17:54
  • Sorry I didn't read it. Its quite big document. Will do. Thanks – m4n07 Feb 25 '13 at 17:57
  • The similarity I am referring to lies in that ftp sets up a seperate conteol channel besides one or more data streams. @M4n07 – alk Feb 25 '13 at 18:10
0

WOO HOO! You've decided to dive into a pretty hairy subject, my friend.

Let me first rephrase your problem: your program can only wait for one thing at a time. If it's waiting on receive, it can't be waiting on send. So you just can't send and receive at the same time.

This is solved by multiplexing: waiting on multiple things.

  1. Googling keywords: io, multiplexing, select, poll.
  2. SO related question: read and write to same socket (TCP) using select

Another approach is to enter a nonblocking-read -> nonblocking-write -> sleep loop. This is obviously less than optimal, but may be enough for your case.

Community
  • 1
  • 1
salezica
  • 74,081
  • 25
  • 105
  • 166
  • Thanks. But i have to receive data at millisecond interval from each of the clients. That is why i'm reluctant to use sleep methods. Is there some pseudocode available. – m4n07 Feb 25 '13 at 18:14
0

I've had some fun in the past designing my own bi-directional protocol for low level devices that can't communicate at the same time. One method you can use is mutual yielding: establish a mechanism for passing messages to and from the client and server. Stream any commands or messages you need to send, then yield the stream to the other side. The other side will then stream any messages or commands, then yield the stream to the original side. The only problem with this mechanism is that it's very laggy with high-ping connections, such as international internet connections.

This has been mentioned already, but I might as well rehash it. Computers have multiplexing built in to their networking hardware already, so you can do "concurrent" send/recv calls. Just run a pair of threads for each connection: a recv thread and a send thread. This should be the most robust solution.

Kaslai
  • 2,445
  • 17
  • 17
0

Presuming you want to have another thread initiate the request to send a command, you can accomplish what you want using standard asynchronous i/o, adding in another channel - a pipe - to receive commands from the other thread. Pseudocode:

Master thread:
while(1) {
    newsocket = accept(listen socket)
    pipefds = pipe()
    new thread(Receiver, newsocket, pipefds.read)
}

Receiver thread:
while(1) {
    readfds = [ pipefds.read, newsocket ]
    poll( readfds )  // wait for there to be data on one of the fds
    if (data ready on newsocket) {
           read (newsocket)
           process data
    }
    if (data ready on pipefds.read) {
           read (pipefds.read)
           send command
    }
}

Commander thread:
write (pipefds.write, command)

The select in the main Receiver loop will wake up whenever there is data to read on the socket, OR if another thread has sent a command that needs to be sent to the remote connection.

Key syscalls to look up info on are poll (or select), and pipe.

evil otto
  • 10,348
  • 25
  • 38