views:

39

answers:

2

I'm implementing an FTP like protocol in Linux (homework) and I came upon the following problem: the client may be able to connect() and write() before the other side managed to do accept() (but after it did listen()). How can I prevent the write operation from working without relying on passing messages like "accept succeeded, you can write now" in a different communication channel?

+4  A: 

The connect() call will not return until a TCP connection is established. Data won't reach the server app until the server side calls accept(). However, once the TCP connection is established the client may start sending data. It will be buffered by the server stack until it is read by the server app.

What is the purpose for preventing the write operation? The TCP window mechanism will pause data flow if the server is delayed in calling accept().

Amardeep
I did check the return value, and also there's this Q3.3: http://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-3.htmlIt's for UNIX, but I have a nagging suspicion it applies to Linux too
EpsilonVector
@EpsilonVector: Once the handshake is completed, the client side may start transmitting. It will be buffered by the server stack until the server app returns from accept() and starts reading. Are you seeing some sort of problem or are you just being cautious?
Amardeep
Now that I know there is buffering, there is no reason to stop in anymore. It also looks like my problem may be unrelated to this thread's topic, so I'll follow the other leads. Thanks anyway.
EpsilonVector
A: 

Look at the TCP three-way handshake in terms of times:

  1. SYN from client to server
    • sent by client at T1
    • received by server at T2
  2. SYN-ACK from server to client
    • sent by server at T3
    • received by client at T4
  3. ACK from client to server
    • sent by client at T5
    • received by server at T6

Blocking connect(2) on the client returns at T5, while blocking accept(2) returns at T6, and T5 is strictly less then T6. So yes, that's the time window where client can start sending data thinking the connection is established. If client's ACK is lost the server is stuck in accept(2). This is similar to well-known race with blocking select(2)/accept(2) combination.

You can't really prevent the client from sending before accept(2) returns on the server without server sending something.

A way around this is making the server socket non-blocking and relying on select(2)/poll(2)/epoll(4).

Nikolai N Fetissov