TCP Sockets represent a basic reliable communication channel between two processes. Most commonly those processes are on separate computers, reached by routing the TCP connection over IP. This page highlights some of the most common ideas needed to program using TCP/IP sockets.
An IP address identifies a computer. A TCP port identifies a connection in one process on that computer. A TCP/IP socket is a bi-directional communication channel with an IP address and TCP port number on each end.
IP addresses are registered and controlled by a hierarchy of agencies; yours was most likely assigned by your Internet Service Provider using DHCP when you connected to the internet.
Port numbers are partially specified by IANA. Unless you are running your computer’s main implementation of one of those assigned ports, code you write should use an unassigned or ephemeral port number, such as a number in the range 49152–65535.
The most common design of a socket-based application is to have one process that is designated as the server. It first opens one socket and waits for any process to send it a message on that socket. When it gets such a message from a client the server opens a second socket on a different port and uses the first connection to tell the client about the second connection, to be used for future communication.
server opens a socket S1 to listen for connection attempts, using three functions:
bind
listen
accept
client opens a socket C1 and uses it to send a connection attempt to S1, using two functions
socket
connect
server opens a socket S2 to be the other end of the C1 connection
This new socket is the return value of accept
both read and write data to their connection socket (S2 and C1, respectively) to communicate, using two function families1 Should you use recv
or read
?
In Python, the socket
object only has recv
, not read
.
In C, read
is more versatile, working with files, pipes, and sockets, while recv
only works for sockets but has a flags
argument supporting additional features.
Both also have a recvfrom
which provides additional information along with the data.
The same points apply to send
and write
.
recv
and its relatives are read
-like functions with additional options for sockets.send
and its relatives are write
-like functions optimized for sockets.Note that for both of these you should avoid using very large buffers. Network packets are generally 4096 bytes or smaller, and it is more efficient to handle each packet as it arrives.
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
unsigned short s1port = /* ... */
// ... inside some function
// prepare address information of the listening socket
struct sockaddr_in ipOfServer;
(&ipOfServer, 0, sizeof(struct sockaddr_in));
memset.sin_family = AF_INET;
ipOfServer.sin_addr.s_addr = htonl(INADDR_ANY);
ipOfServer.sin_port = htons(s1port);
ipOfServer
// create listening socket and connect it to its address
int listener = socket(AF_INET, SOCK_STREAM, 0);
(listener, (void *)&ipOfServer , sizeof(ipOfServer));
bind
// use socket to wait for connections
// if several arrive, suggest the OS queue up 20
(listener, 20);
listen
// repeat to allow multiple clients to connect
while(1) {
// wait for a client connection
int connection = accept(listener, NULL, NULL);
// ... read (or recv) from and write (or send) to connection
// ... then close(connection)
}
(listener);
close
// ...
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
unsigned short s1port = /* ... */
const char * serverIP = /* ... */
// ... inside some function
// prepare address information of the socket
struct sockaddr_in ipOfServer;
(&ipOfServer, 0, sizeof(struct sockaddr_in));
memset.sin_family = AF_INET;
ipOfServer.sin_addr.s_addr = inet_addr(serverIP);
ipOfServer.sin_port = htons(s1port);
ipOfServer
// create listening socket and connect it to its address
int connection = socket(AF_INET, SOCK_STREAM, 0);
(connection, (void *)&ipOfServer, sizeof(struct sockaddr_in));
connect
// ... read (or recv) from and write (or send) to connection
// ... then close(connection)
// ...
from socket import socket, AF_INET, SOCK_STREAM
= # ...
s1port
# create the listening socket
with socket(AF_INET, SOCK_STREAM) as listener:
'', s1port))
listener.bind((
# use socket to wait for connections
# if several arrive, suggest the OS queue up 20
20);
listener.listen(
# repeat to allow multiple clients to connect
while True:
= listener.accept()
connection, addr
# ... send to and recv from connection
# ... then connection.close()
from socket import socket, AF_INET, SOCK_STREAM
= # ...
s1port = # ...
serverIP
# create the listening socket
with socket(AF_INET, SOCK_STREAM) as connection:
connect((serverIP, s1port))
connection.
# ... send to and recv from connection
# (automatically closed by with block)