The Socket API, Part 3: Concurrent Servers
2013-12-10 18:31
344 查看
转:http://www.linuxforu.com/2011/10/socket-api-part-3-concurrent-servers/
By Pankaj Tanwar on October 1, 2011 in Coding, Developers · 2 Comments
In this part of the series, we will learn how to deal with multiple clients connected to the server.
Welcome to another dose of socket programming! Till now, we’ve created servers that are capable of creating connections with multiple clients [Part 1 & Part 2], but the problem is that the server will communicate with only one client at any point in time. This is because there is only one socket descriptor,
Here is the code included from the previous article. This time it is for IPv4…
Let’s see what we’ve done here. At line 23, after getting the socket descriptor
The server, on the other hand, where
Another method of doing this is using threads, but we’re not getting into that right now.
Now, compile, run and see the server running and handling multiple clients. See Figure 1 — I’m running the server on a network now (;) though these clients are VirtualBox running VMs with Backtrack (192.168.1.19) and Arch (192.168.1.4), and Android phone running ConnectBot to create a TCP connection.
Figure 1: Server screen
Also run
Figure 2: Output of netstat
We can also see the parent server process LISTENing and the ESTABLISHED connections, with IPs and ports.
We added
Let’s examine some code from the
The problem is whether the blocked system call, after running the signal handler, will be restarted or not. We can look at this later, when we write our own signal handler — or just go check the
Now, just receive the signal and ignore it by setting handler to
These system calls wait for a state change in the child, such as the child being terminated or stopped by a signal, or resumed by a signal (check the man pages).
In Figure 3, the rectangles represent the states, and the edges, the transitions.
Figure 3: TCP state diagram
We need to visualise the server and client in the diagram. Two edges come out of the CLOSED state; one is Active Open. This transition occurs when a client sends a SYN packet to the server, and the system is initiating the connection. Another is Passive Open, where the server enters the listen state and waits for connections.
First, from the client side, after the SYN is sent the client enters the
Receiving the FIN from the server will result in sending the ACK, and going to the
For the server, passive open is the LISTEN state. Receiving a SYN results in sending SYN and ACK, and going to the
After the operation completes, the server sends the FIN, and transitions to the
Here we can see the “ThreeHandshake” — the exchange of three packets to establish a TCP connection. It is initiated when the client calls
To terminate the connection, we need four packets. The client calls
Here’s where I close the connection, even though it was short this time! Next month, I’ll be back with a new connection to socket programming… you can now ACK my FIN!
By Pankaj Tanwar on October 1, 2011 in Coding, Developers · 2 Comments
In this part of the series, we will learn how to deal with multiple clients connected to the server.
Welcome to another dose of socket programming! Till now, we’ve created servers that are capable of creating connections with multiple clients [Part 1 & Part 2], but the problem is that the server will communicate with only one client at any point in time. This is because there is only one socket descriptor,
cfd, created to communicate with a client — and all connections will wait on the same descriptor. Now, let’s use the
fork()system call to fork a copy of the server for each client.
Here is the code included from the previous article. This time it is for IPv4…
cfdfrom the call to accept, we forked the server. The child process (where
pid==0) closes the listening descriptor with
close(sfd), does the work the server is intended to do, and when finished, closes the descriptor and returns (see lines 27-39).
The server, on the other hand, where
pid>0, just closes the
cfd(line 39), and is again ready to accept more connections. Thus, for each incoming connection, a new server process will be created.
Another method of doing this is using threads, but we’re not getting into that right now.
Now, compile, run and see the server running and handling multiple clients. See Figure 1 — I’m running the server on a network now (;) though these clients are VirtualBox running VMs with Backtrack (192.168.1.19) and Arch (192.168.1.4), and Android phone running ConnectBot to create a TCP connection.
Figure 1: Server screen
Also run
netstat -a | grep 1205to check for current network connections; I’ve greped 1205, our port, to show only connections to our server (see Figure 2).
Figure 2: Output of netstat
We can also see the parent server process LISTENing and the ESTABLISHED connections, with IPs and ports.
We added
signal(SIGCHLD, SIG_IGN)to the code to prevent child processes going into a zombie state. A child process, when it finishes (a clean termination or killed by some signal), returns the exit status to its parent process, which is notified by the
SIGCHLDsignal sent by the system. If the parent doesn’t handle this signal, the child process still uses some memory, and remains in a zombie state. If the parent finishes before the child, or doesn’t collect the status and terminates, the status will be provided to the parent of all processes, i.e.,
initwith
pid 1.
Let’s examine some code from the
signal()man page:
signal()sets the disposition of the signal
signumto handler, which is either
SIG_IGN,
SIG_DFL, or the address of a programmer-defined function (a “signal handler”). It also indicates that the behaviour of
signal()differs among different Linux and UNIX versions, and tells us to use
sigaction()instead.
The problem is whether the blocked system call, after running the signal handler, will be restarted or not. We can look at this later, when we write our own signal handler — or just go check the
sigactionstructure in the man pages.
Now, just receive the signal and ignore it by setting handler to
SIG_IGN. This will not let the child enter a zombie state. What if the parent finishes before the child (though not the case here, because the server is in an infinite loop)? In that case, the parent can wait for the child using
wait()or
waitpid()calls, of which
waitpid()is preferred.
These system calls wait for a state change in the child, such as the child being terminated or stopped by a signal, or resumed by a signal (check the man pages).
A little science
Now, before moving further, let’s talk about TCP here since better code requires a sound understanding of the basics.In Figure 3, the rectangles represent the states, and the edges, the transitions.
Figure 3: TCP state diagram
We need to visualise the server and client in the diagram. Two edges come out of the CLOSED state; one is Active Open. This transition occurs when a client sends a SYN packet to the server, and the system is initiating the connection. Another is Passive Open, where the server enters the listen state and waits for connections.
First, from the client side, after the SYN is sent the client enters the
SYN_SENTstate. Now, after receiving the SYN from the server and sending SYN and ACK, it transitions to ESTABLISHED. From the ESTABLISHED state (where communication takes place), sending a FIN will initiate an Active Close to terminate the connection, and enter the
FIN_WAIT_1state. Receiving ACK will move it to the
FIN_WAIT_2state.
Receiving the FIN from the server will result in sending the ACK, and going to the
TIME_WAITstate. In this state, the system waits for twice the MSL (maximum segment lifetime); the recommended value in RFC 1337 is 120 seconds, Linux implements 60 seconds. This state helps reliable termination ofconnections in case of lost packets, and allows old duplicate segments to expire in the network. Finally, it goes to the CLOSED state.
For the server, passive open is the LISTEN state. Receiving a SYN results in sending SYN and ACK, and going to the
SYN_RCVDstate. Receiving an ACK will take the server to the ESTABLISHED state for data communication. Then, receiving a FIN will result in sending an ACK, and will initiate the passive close and it going to the
CLOSE_WAITstate.
After the operation completes, the server sends the FIN, and transitions to the
LAST_ACKstate. On receiving the ACK, it will terminate the connection and go to the CLOSED state.
Here we can see the “ThreeHandshake” — the exchange of three packets to establish a TCP connection. It is initiated when the client calls
connect(). Packet 1 is SYN x from client to server; Packet 2 is ACK x+1 and SYN y from server to client; and Packet 3 is ACK y+1 from client to server. Here, x is the sequence number from the client, and y the sequence number from the server.
To terminate the connection, we need four packets. The client calls
close()to initiate termination: Packet 1 is FIN m from client to server; and Packet 2 is ACK m+1 from server to client. Now, the server finishes the operation, and then calls
close()and sends its FIN n. The client sends ACK n+1 to terminate the connection.
Here’s where I close the connection, even though it was short this time! Next month, I’ll be back with a new connection to socket programming… you can now ACK my FIN!
相关文章推荐
- Creating Your Own Server: The Socket API, Part 1
- Creating Your Own Server: The Socket API, Part 2
- The Socket API, Part 4: Datagrams
- The Socket API, Part 5: SCTP
- iOS-Performing Common Peripheral Role Tasks(API Reference)the fourth part
- iOS-Best Practices for Interacting with a Remote Peripheral Device(API Reference) the sixth part
- iOS-Best Practices for Setting Up Your Local Device as a Peripheral(API Reference) the seventh part
- The API Gateway Pattern: Angular JS and Spring Security Part IV
- LINUX SOCKET PART 2: THE SERVER SIDE ISSUES
- iOS-Core Bluetooth Overview(API Reference) of the second part
- iOS-Core Bluetooth Background Processing for iOS Apps(API Reference) the fifth part
- Opening Doors: Notes On the Delphi ToolsAPI by its Creator - Part 2 - by Allen Bauer
- An Introduction to the Java Logging API (part)
- iOS-Performing Common Central Role Tasks(API Refrence) of the third part
- The WebSocket API
- Inside the Windows Vista Kernel: Part 1
- Calculate the area of dashed part
- 1. [SDL-API]Initializing the Library
- Java theory and practice: Fixing the Java Memory Model, Part 2
- The Browser Exploitation Framework (BeEF) – Part 1