C TCP Socket Programming Examples
C TCP Socket Programming Examples
The TCP client sends three integers in a single message to the server. The server reads these values into an integer array. The server then calculates the sum, difference, and product of these three numbers. These results are stored in another integer array, which is sent back to the client. The client receives this data, extracts the results, and prints the sum, difference, and product as the final output .
Socket options related to the IP layer that can be retrieved include `IP_TTL` for the time-to-live value and `IP_TOS` for the type of service. For the TCP layer, options include `TCP_NODELAY` for disabling Nagle's algorithm, `TCP_MAXSEG` for maximum segment size, `TCP_KEEPIDLE` for the time before starting keepalives, `TCP_KEEPCNT` for the number of keepalive probes, `TCP_KEEPINTVL` for the interval between keepalive probes, and `TCP_WINDOW_CLAMP` for setting the TCP receive window size. These options are retrieved using the `getsockopt()` function and written to a file .
The C client program first establishes a connection to the server using a TCP socket. Upon connection, the client program prepares to receive image data by opening a file in write mode using `open()`. It reads the image data in chunks from the socket using the `recv()` function and writes each chunk to the file using the `write()` function. This loop continues until all data is received and written, concluding by closing the file to ensure all data is correctly saved and resources are released .
The `bind()` function associates a socket with a specific local IP address and port number, thus specifying where on the network the server will listen for incoming connections. This step is crucial for any server as it determines the access point for clients. The `listen()` function follows `bind()`, placing the socket in a passive mode to accept incoming connection requests. This function specifies a queue limit for incoming connection requests, indicating the server is ready to handle client connections. Both functions work in tandem: `bind()` sets the endpoint, while `listen()` initiates the waiting process for connections .
The Java ImageServer program first creates a `ServerSocket` to listen on a specific port. Upon accepting a client connection, it opens a `FileInputStream` to read the image file in chunks into a buffer. These chunks are then written to the client's `OutputStream` repeatedly until the entire file is sent. This loop continues until `read()` returns -1, indicating the end of the file, ensuring the entire file is transmitted. Finally, the streams and the socket are closed to release resources .
The `close()` function is critical as it frees up the resources associated with the socket, both on the client and server sides. If neglected, it can lead to resource leaks where operating system resources (file descriptors and network ports) are not released after use, potentially exhausting these resources and causing errors in socket creation or connection acceptance. Additionally, not closing sockets properly can lead to incomplete data transmission and may not release network-channel bandwidth, which can affect network performance and application stability .
First, a socket is created using the `socket()` function with parameters `AF_INET` for IPv4 and `SOCK_STREAM` for a TCP connection. Next, the server's address structure is initialized, specifying `AF_INET` in the `sin_family` field and setting `sin_addr.s_addr` to `INADDR_ANY` for binding to all interfaces. The `sin_port` field is set using `htons()` to ensure proper byte order of the port number. The socket is then bound to this address using the `bind()` function. Finally, the `listen()` function is called to put the socket into a listening state to accept incoming connections .
Pipes provide a unidirectional communication channel and are typically used for parent-child process communication on the same machine. They do not require creating server/client socket pairs and are simpler, but limited to local communication. Sockets, however, support bidirectional communication and can be used for network communication between processes on different machines. Sockets require setting up network protocols (like TCP/UDP), making them more complex but versatile compared to pipes. While pipes have lower overhead, sockets offer wider use-cases, including internet-based communication, with added complexity and resource usage .
The `inet_pton()` function is used to convert a human-readable IP address in standard text form (IPv4 or IPv6) to its binary form used within network programs. This conversion is essential to pass the structured binary IP address to low-level socket functions for establishing a connection, as these functions do not work with textual IP representations. Using `inet_pton()` ensures proper interpretation and validation of the IP address format, reducing errors in network connections .
The sequence starts with creating a socket using `socket()`, specifying `SOCK_STREAM` for TCP. The `bind()` call associates the socket with an IP address and port. The `listen()` call then marks the socket as receptive to incoming connections. Following this, `accept()` is used to actually accept an incoming client connection, producing a new socket for communication with that specific client. `read()` or `recv()` handles incoming data, while `write()` or `send()` outputs data to the client. Finally, `close()` is called to release resources for each socket when done. Each call serves a distinct role from initialization to communication and connection termination .