English | 中文版
[TOC]
#include <netinet/in.h>
struct sockaddr_storage {
uint8_t ss_len;
sa_family_t ss_family;
};#include <netinet/in.h>
struct in_addr {
in_addr_t s_addr; // At least 32-bit unsigned integer type
};
struct sockaddr_in {
uint8_t sin_len; // Length field
sa_family_t sin_family; // Address family; any unsigned integer type
in_port_t sin_port; // TCP or UDP port; at least 16-bit unsigned integer type
struct in_addr sin_addr;
char sin_zero[8];
};#include <netinet/in.h>
struct in6_addr {
uint8_t s6_addr[16];
};
#define SIN6_LEN
struct sockaddr_in6 {
uint8_t sin6_len;
sa_family_t sin6_family;
in_port_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
}- Functions passing socket address structures from process to kernel:
bindconnectsendto
- Functions passing socket address structures from kernel to process:
acceptrecvfromgetsocknamegetpeername
TODO
TODO
#include <sys/socket.h>
int socket(int family, int type, int protocol)familyprotocol familyfamily Description AF_INET IPv4 protocol AF_INET6 IPv6 protocol AF_LOCAL Unix domain AF_ROUTE Routing socket AF_KEY Key socket typesocket typetype Description SOCK_STREAM Byte stream socket SOCK_DGRAM Datagram socket SOCK_SEQPACKET Sequenced packet SOCK_RAW Raw socket protocolprotocol typeprotocol Description IPPROTO_TCP TCP protocol IPPROTO_UDP UDP protocol IPPROTO_SCTP SCTP protocol return valueSuccess: socket descriptor (non-negative) Failure: -1 Creates a socket and returns a socket descriptor
| AF_INET | AF_INET6 | AF_LOCAL | AF_ROUTE | AF_KEY | |
|---|---|---|---|---|---|
| SOCK_STREAM | TCP/SCTP |
TCP/SCTP |
Yes | ||
| SOCK_DGRAM | UDP | UDP | Yes | ||
| SOCK_SEQPACKET | SCTP | SCTP | Yes | ||
| SOCK_RAW | IPv4 | IPv6 | Yes | Yes | |
Possible combinations of socket family and type |
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen)sockfdsocket descriptorservaddrpointer to socket addressaddrlensocket address lengthreturn valueSuccess: 0 Failure: -1 Establish a connection to a TCP server
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen)sockfdsocketmyaddrpointer to protocol-specific address structureaddrlenlength of address structurereturn valueSuccess: 0 Failure: -1 Bind address (assign a local protocol address to a socket)
#include <sys/socket.h>
int listen(int sockfd, int backlog);sockfdsocketbacklogmax length of pending socket queuereturn valueSuccess: 0 Failure: -1 Listen on a socket (convert an unconnected socket to a passive socket, instructing the kernel to accept connection requests to the socket, and set the max length of the pending socket queue)
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);sockfdlistening socketcliaddrreturns connected protocol addressaddrlenreturns length of connected protocol addressreturn valueSuccess: a new descriptor Failure: error code Accept connection (returns the next completed connection from the head of the completed connection queue; if the queue is empty, the process sleeps)
#include <unistd.h>
int close(int sockfd);sockfdsocket file descriptorreturn valueSuccess: 0 Failure: -1 Marks the socket as closed so it can no longer be used by read or write
#include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);sockfdsocket file descriptorlocaladdrlocal protocol addressaddrlenlength of local protocol addressreturn valueSuccess: 0 Failure: -1 Returns the local protocol address associated with the socket
#include <sys/socket.h>
int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);sockfdsocket file descriptorpeeraddrremote protocol addressaddrlenlength of remote protocol addressreturn valueSuccess: 0 Failure: -1 Returns the remote protocol address associated with the socket (getpeername)
#include <sys/socket.h>
int shutdown(int sockfd, int howto);sockfdsocket file descriptorhowtoactionAction Description SHUT_RD Close read, discard data in receive buffer. SHUT_WR Close write, discard data in send buffer. SHUT_RDWR Close read and write, like calling SHUT_RDandSHUT_WR.return valueSuccess: 0 Failure: -1 Close connection
#include <fcntl.h>
int fcntl(int fd, int cmd, ...)fdfile descriptorcmdcommandreturn valueSuccess: depends on cmd Failure: -1 Performs various descriptor control operations.
#include <unistd.h>
int ioctl(int fd, int request, ...);fdsocketrequestrequestreturn valueSuccess: 0 Failure: -1 Affects an open file referenced by fd.
| Operation | fcntl | ioctl | Routing Socket | POSIX |
|---|---|---|---|---|
| Set socket to non-blocking I/O | F_SETFL, O_NONBLOCK | FIONBIO | fcntl | |
| Set socket to signal-driven I/O | F_SETFL, O_ASYNC | FIOASYNC | fcntl | |
| Set socket owner | F_SETOWN | SIOCSPGRP or FIOSETOWN | fcntl | |
| Get socket owner | F_GETOWN | SIOCGPGRP or FIOGETOWN | fcntl | |
| Get bytes in receive buffer | FIONREAD | |||
| Test if socket is at out-of-band mark | SIOCATMARK | sockatmark | ||
| Get interface list | SIOCGIFCONF | sysctl | ||
| Interface operations | SIOC[GS]IFxxx | |||
| ARP cache operations | SIOCxARP | RTM_xxx | ||
| Routing table operations | SIOCxxxRT | RTM_xxx |
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);sockfd: socketlevel: level, specifies the code in the system that interprets the option, either general socket code or protocol-specific codeoptname: option nameoptval: pointer to a variableoptlen: size of optval- return value Success: 0 Failure: -1 Get socket option
#include <sys/socket.h>
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);sockfd: socketlevel: level, specifies the code in the system that interprets the option, either general socket code or protocol-specific codeoptname: option nameoptval: pointer to an option variableoptlen: size of optval- return value
- Success: 0
- Failure: -1 Set socket option
TODO
| level | optname | Data Type | Description |
|---|---|---|---|
| SOL_SOCKET | SO_BROADCAST SO_DEBUG SO_DONTROUTE SO_ERROR SO_KEEPALIVE SO_LINGER SO_OOBINLINE SO_RCVBUF SO_SNDBUF SO_RCVLOWAT SO_SNDLOWAT SO_RCVTIMEO SO_SNDTIMEO SO_REUSEADDR SO_REUSEPORT SO_TYPE SO_USELOOPBACK |
int int int int int linger int int int int int timeval timeval int int int int |
- Allow sending broadcast datagrams - Enable debug tracing - Bypass outbound routing table lookup - Get and clear pending errors - Periodically test if connection is alive - Delay close if data is pending - Keep received out-of-band data inline - Receive buffer size - Send buffer size - Receive buffer low-water mark - Send buffer low-water mark - Receive timeout - Send timeout - Allow reuse of local address - Allow reuse of local port - Get socket type - Routing socket gets a copy of sent data |
| IPPROTO_IP | IP_HDRINCL IP_OPTIONS IP_RECVDSTANDDR IP_RECVIF IP_TOS IP_TTL IP_MULTICAST_IF IP_MULTICAST_TTL IP_MULTICAST_LOOP IP_ADD_MEMBERSHIP IP_DROP_MEMBERSHIP IP_BLOCK_SOURCE IP_UNBLOCK_SOURCE IP_ADD_SOURCE_MEMBERSHIP IP_DROP_SOURCE_MEMBERSHIP |
int (see text) int int int int in_addr{} u_char u_char ip_mreq{} ip_mreq{} ip_mreq_source{} ip_mreq_source{} ip_mreq_source{} ip_mreq_source{} |
- Include IP header with data - IP header options - Return destination IP address - Return receiving interface index - Service type and priority - Time to live - Specify outgoing interface - Specify outgoing TTL - Specify loopback - Join multicast group - Leave multicast group - Block multicast group - Unblock multicast group - Join source-specific multicast group - Leave source-specific multicast group |
| IPPROTO_ICMPV6 | ICMP6_FILTER | ivmp6_filter{} | - Specify ICMPv6 message types to deliver |
| IPPROTO_IPV6 | IPV6_CHECKSUM IPV6_DONTFRAG IPV6_NEXTHOP IPV6_PATHMTU IPV6_RECVDSTOPTS IPV6_RECVHOPLIMIT IPV6_RECVHOPOPTS IPV6_RECVPATHMTU IPV6_RECVPKTINFO IPV6_RECVRTHDR IPV6_RECVTCLASS IPV6_UNICAST_HOPS IPV6_USE_MIN_MTU IPV6_V60NLY IPV6_XXX IPV6_MULTICAST_IP IPV6_MULTICAST_HOPS IPV6_MULTICAST_LOOP IPV6_JOIN_GROUP IPV6_LEAVE_GROUP |
int int sockaddr_in6{} ip6_mtuinfo{} int int int int int int int int int int (see text) u_int int u_int ipv6_mreq{} ipv6_mreq{} |
- Checksum offset for raw sockets - Drop large packets instead of fragmenting - Specify next hop address - Get current path MTU - Receive destination options - Receive unicast hop limit - Receive hop-by-hop options - Receive path MTU - Receive packet info - Receive source route - Receive traffic class - Default unicast hop limit - Use minimum MTU - Disable v4 compatibility - Sticky ancillary data - Specify outgoing interface - Specify outgoing hop limit - Specify loopback - Join multicast group - Leave multicast group |
| IPPROTO_IP IPPROTO_IPV6 |
MCAST_JOIN_GROUP MCAST_LEAVE_GROUP MCAST_BLOCK_SOURCE MCAST_UNBLOCK_SOURCE MCAST_JOIN_SOURCE_GROUP MCAST_LEAVE_SOURCE_GROUP |
group_req{} group_source_req{} group_source_req{} group_source_req{} group_source_req{} group_source_req{} |
- Join multicast group - Leave multicast group - Block multicast source - Unblock multicast source - Join source-specific multicast group - Leave source-specific multicast group |
| level | optname | Data Type | Description |
|---|---|---|---|
| IPPROTO_TCP | TCP_MAXSEG TCP_NODELAY |
int int |
- TCP max segment size - Disable Nagle algorithm |
| IPPROTO_SCTP | SCTP_ADAPTION_LAYER SCTP_ASSOCINFO SCTP_AUTOCLOSE SCTP_DEFAULT_SEND_PARAM SCTP_DISABLE_FRAGMENTS SCTP_EVENTS SCTP_GET_PEER_ADDR_INFO SCTP_I_WANT_MAPPED_V4_ADDR SCTP_INITMSG SCTP_MAXBURST SCTP_MAXSEG SCTP_NODELAY SCTP_PEER_ADDR_PARAMS SCTP_PRIMARY_ADDR SCTP_RTOINFO SCTP_SET_PEER_PRIMARY_ADDR SCTP_STATUS |
sctp_setadaption{} sctp_assocparams{} int sctp_sndrcvinfo{} int sctp_event_subscribe{} sctp_paddrinfo{} int sctp_initmsg{} int int int sctp_paddrparams{} sctp_setprim{} sctp_rtoinfo{} sctp_setpeerprim{} sctp_status{} |
- Adaptation layer indication - Check and set association info - Auto close operation - Default send params - SCTP fragmentation - Notification of interested events - Get peer address status - Mapped v4 address - Default INIT params - Max burst size - Max segment size - Disable Nagle algorithm - Peer address params - Primary destination address - RTO info - Peer primary destination address - Get association status |
struct sockaddr_dl {
uint8_t sdl_len;
sa_family_t sdl_family;
uint16_t sdl_index;
uint8_t sdl_type;
uint8_t sdl_nlen;
uint8_t sdl_alen;
uint8_t sdl_slen;
char sdl_data[12];
};#include <sys/param.h>
#include <sys/sysctl.h>
int sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen);namename (integer array)- AF_INET: get/set variables affecting the Internet protocol.
- AF_LINK: get/set link layer info (e.g., number of PPP interfaces).
- AF_ROUTE: returns info about routing table or interface list
sysctl returns info in AF_ROUTE domain:
name[] Returns IPv4 routing table Returns IPv4 ARP cache Returns IPv6 routing table Returns interface list 0 CTL_NET CTL_NET CTL_NET CTL_NET 1 AF_ROUTE AF_ROUTE AF_ROUTE AF_ROUTE 2 0 0 0 0 3 AF_INET AF_INET AF_INET6 0 4 NET_RT_DUMP NET_RT_FLAGS NET_RT_DUMP NET_RT_IFLIST 5 0 RTF_LLINFO 0 0 - AF_UNSPEC: get/set some socket layer variables (e.g., max send/recv buffer size).
namelenarray lengtholdpbuffer for kernel to store name May contain:- NET_RT_DUMP: returns routing table for address family specified by name[3]. If 0, returns all address families.
- NET_RT_FLAGS: returns routing table for address family specified by name[3], but only entries with flags matching name[5]. All ARP cache entries in routing table have RTF_LLINFO flag set.
- NET_RT_IFLIST: returns info for all configured interfaces.
oldlenpbuffer size for kernel to store namenewpbuffernewlenbuffer sizereturn valueSuccess: 0 Failure: -1 Check routing table and interface list, create routing socket.
#include <sys/socket.h>
size_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags, struct sockaddr *from, socklen_t *addrlen)sockfddescriptorbuffbuffer pointernbytesnumber of bytes to readfromsender addressaddrlenaddress lengthreturn valueSuccess: number of bytes read Failure: -1 Receive message (recvfrom needs timeout option, otherwise it will block forever).
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buff, size_t nbytes, int flags, const struct sockaddr *to, socklen_t *addrlen)sockfddescriptorbuffbuffer pointernbytesnumber of bytes to read/writeflagsparametertoreceiver addressaddrlenaddress lengthreturn valueSuccess: number of bytes written Failure: -1 Send message
TODO
TODO
TODO
Socket send buffer after application writes 1 byte of out-of-band data
#include <sys/socket.h>
int sockatmark(int sockfd);sockfdsocket descriptorreturn value1: at out-of-band mark 0: not at out-of-band mark -1: failure Check if socket is at out-of-band mark
Raw sockets provide the following capabilities not available with regular TCP and UDP sockets:
- Processes can read and write ICMPv4, IGMPv4, and ICMPv6 packets.
- Processes can read and write IPv4 datagrams whose protocol fields are not handled by the kernel.
- Processes can use the IP_HDRINCL socket option to construct IPv4 headers themselves.
- Specify SOCK_RAW as the second argument to socket to create a raw socket; the third argument (protocol) is usually nonzero.
Example:
int sockfd; sockfd = socket(AF_INET, SOCK_RAW, protocol); - You can enable the IP_HDRINCL socket option on a raw socket.
Example:
const int on = 1; if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) // error handling
- You can call bind on a raw socket to set the source IP address for all datagrams sent from this raw socket (only if IP_HDRINCL is not enabled).
- You can call connect on this raw socket to set the remote address.
Raw socket output follows these rules:
- Normal output is done by calling sendto or sendmsg and specifying the destination IP address. If the socket is already connected, you can also call write, writev, or send.
- If IP_HDRINCL is not enabled, the data to be sent by the process starts at the first byte after the IP header, as the kernel will construct the IP header and prepend it to the data. The protocol field of the constructed IPv4 header is set to the third argument of the socket call.
- If IP_HDRINCL is enabled, the data to be sent by the process starts at the first byte of the IP header. The amount of data written by the output function must include the size of the IP header. The entire IP header is constructed by the process.
Notes:
- The IPv4 identification field can be set to 0, telling the kernel to set this value;
- The IPv4 header checksum field is always calculated and stored by the kernel;
- The IPv4 options field is optional.
- The kernel will fragment raw packets that exceed the MTU of the outgoing interface.
Differences for IPv6 raw sockets compared to IPv4:
- All fields in protocol headers sent and received via IPv6 raw sockets are in network byte order;
- IPv6 does not have an option like IP_HDRINCL in IPv4. You cannot read or write a complete IPv6 packet (including the IPv6 header and any extension headers) via an IPv6 raw socket. Almost all fields of the IPv6 header and all extension headers can be specified or obtained by the application via socket options or ancillary data. If the application needs to read or write a complete IPv6 datagram, it must use data link access.
- Checksum handling for IPv6 raw sockets is different.
The kernel passes received IP datagrams to raw sockets according to these rules:
- Received UDP and TCP packets are never delivered to any raw socket.
- Most ICMP packets are delivered to raw sockets after the kernel processes the ICMP message.
- All IGMP packets are delivered to raw sockets after the kernel processes the IGMP message.
- All IP datagrams with unknown protocol fields are delivered to raw sockets.
- If a datagram arrives as fragments, no fragment is delivered to raw sockets until all fragments have arrived and the datagram is reassembled.
The kernel performs the following three tests for each raw socket; only if all three are true will the datagram be delivered to the socket:
- If a nonzero protocol parameter was specified when creating the raw socket (third argument to socket), the protocol field of the received datagram must match this value, otherwise the datagram is not delivered to this socket.
- If the raw socket was bound to a local IP address via bind, the destination IP address of the received datagram must match this bound address, otherwise the datagram is not delivered to this socket.
- If the raw socket was connected to a remote IP address via connect, the source IP address of the received datagram must match this connected address, otherwise the datagram is not delivered to this socket.
#include <netinet/icmp6.h>
void ICMP6_FILTER_SETPASSALL(struct icmp6_filter *filt); // Pass all message types to the application
void ICMP6_FILTER_SETBLOCKALL(struct icmp6_filter *filt); // Block all message types
void ICMP6_FILTER_SETPASS(int msgtype, struct icmp6_filter *filt); // Pass a specific message type to the application
void ICMP6_FILTER_SETBLOCK(int msgtype, struct icmp6_filter *filt); // Block a specific message type
int ICMP6_FILTER_WILLPASS(int msgtype, const struct icmp6_filter *filt); // Check if message type is passed by the filter
int ICMP6_FILTER_WILLBLOCK(int msgtype, const struct icmp6_filter *filt);// Check if message type is blocked by the filter
TCP/IP stream-based implementation
struct strbuf {
int maxlen;
int len;
char *buf;
};#include <stropts.h>
int getmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, int *flagsp);fdfile descriptorctlptrcontrol infodataptrdataflagspflag pointerflagsp Description 0 Normal message RS_HIPRI High priority Receive control info and data.
#include <stropts.h>
int putmsg(int fd, const struct strbuf *ctlptr, const struct strbuf *dataptr, int flags);fdfile descriptorctlptrcontrol infodataptrdataflagsflag Send control info and data.
#include <stropts.h>
int getpmsg(int fd, struct strbuf *ctlptr, struct strbuf *dataptr, int *bandp, int *flagsp);fdfile descriptorctlptrcontrol infodataptrdatabandppriority bandflagspflag Receive control info and data with priority.
#include <stropts.h>
int putpmsg(int fd, const struct strbuf *ctlptr, const struct strbuf *dataptr, int band, int flags);fdfile descriptorctlptrcontrol infodataptrdatabandppriority bandflagspflag Send control info and data with priority.
struct sockaddr_un {
sa_family_t sun_family;
char sun_path[104];
};#include <sys/socket.h>
int socketpair(int family, int type, int protocol, int sockfd[2]);familyprotocol family (must be AF_LOCAL)typetype (one of SOCK_STREAM or SOCK_DGRAM)protocolprotocol (must be 0)sockfdreturns newly created socket descriptorsreturn valueSuccess: nonzero Failure: -1 Creates two sockets that are then connected to each other
TODO Load winsock DLL.
TODO
TODO
TODO
TODO
TODO
TODO
TODO
client.cpp:
#include <winsock2.h>
#include <WS2tcpip.h>
#include <iostream>
#include <stdlib.h>
// Link WS2_32
#pragma comment(lib, "ws2_32.lib")
#define BUFSIZE 4096 // Buffer size
int main(int argc, char *argv[])
{
WSADATA wsd;
SOCKET sock;
char buf[BUFSIZE];
int ret;
struct sockaddr_in serv_addr;
unsigned short port;
struct hostent *host = NULL;
// Load specified version of dll
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
std::cout << "Initialization failed!!!" << std::endl;
return 1;
}
// Create socket
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
std::cout << "Socket creation failed" << std::endl;
return 1;
}
// Specify server address
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(10086);
inet_pton(AF_INET, "localhost", (void*)&serv_addr.sin_addr.S_un.S_addr);
//serv_addr.sin_addr.s_addr = inet_addr("localhost"); // inet_addr is deprecated
// Connect to server
if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR) {
std::cout << "connect() failed" << std::endl;
return 1;
}
// Send/receive messages
for (;;) {
gets_s(buf);
// Send message to server
ret = send(sock, buf, strlen(buf), 0);
if (ret == 0)
break;
else if (ret == SOCKET_ERROR) {
std::cout << "send() failed" << std::endl;
}
buf[ret] = '\0';
std::cout << "recv :" << ret << " bytes:" << buf;
}
// Close socket, release resources
closesocket(sock);
WSACleanup();
system("pause");
return 0;
}serv.cpp:
#include <winsock2.h>
#include <WS2tcpip.h>
#include <iostream>
#include <stdlib.h>
#pragma comment(lib, "ws2_32.lib")
#define DEFAULT_BUFFER 4096 // Buffer size
// Thread function for communicating with client
DWORD WINAPI ClientThread(LPVOID lpParam)
{
SOCKET sock = (SOCKET)lpParam;
char buf[DEFAULT_BUFFER];
int ret, nleft, idx;
while (true) {
// Receive message
ret = recv(sock, buf, DEFAULT_BUFFER, 0);
if (ret == 0)
break;
else if (ret == SOCKET_ERROR) {
std::cout << "recv() failed:" << WSAGetLastError();
break;
}
buf[ret] = '\0';
std::cout << "recv: " << buf; // Print message
nleft = ret;
idx = 0;
while (nleft > 0) {
// Send response message
ret = send(sock, &buf[idx], nleft, 0);
if (ret == 0)
break;
else if (ret == SOCKET_ERROR) {
std::cout << "send() failed:" << WSAGetLastError();
break;
}
nleft -= ret;
idx += ret;
}
}
return 0;
}
int main()
{
WSADATA wsd;
HANDLE hThread;
DWORD dwThread;
SOCKET sListen, sClient;
int AddrSize;
unsigned short port;
struct sockaddr_in local, client;
// Load winsock dll
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
std::cout << "winsock initialization failed" << std::endl;
return 1;
}
// Create socket
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (sListen == SOCKET_ERROR) {
std::cout << "socket() failed:" << WSAGetLastError();
return 1;
}
local.sin_family = AF_INET;
local.sin_addr.s_addr = htonl(INADDR_ANY);
port = 10086;
local.sin_port = htons(port);
// Bind socket
if (bind(sListen,
(struct sockaddr*)&local,
sizeof(local)) == SOCKET_ERROR) {
std::cout << "bind() failed:" << WSAGetLastError();
return 1;
}
// Listen
listen(sListen, 0);
// Listen for connections, create threads
while (true) {
AddrSize = sizeof(client);
// Listen for connection requests
sClient = accept(sListen, (struct sockaddr*)&client, &AddrSize);
if (sClient == INVALID_SOCKET) {
std::cout << "accept() failed:" << WSAGetLastError();
break;
}
// Create thread
hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)sClient, 0, &dwThread);
if (hThread == NULL) {
std::cout << "CreateThread() failed:" << GetLastError();
break;
}
// Close after handling
CloseHandle(hThread);
}
closesocket(sListen);
WSACleanup();
system("pause");
return 0;
}- When system load is light, the traditional concurrent server model that forks a child process for each client request is sufficient.
- Compared to the traditional fork-per-client design, pre-creating a pool of child processes or threads can reduce process control CPU time by 10x or more.
- Some implementations allow multiple child processes or threads to block on the same accept call, while others require some type of lock around accept. File locking or pthread mutexes can be used.
- Letting all child processes or threads call accept themselves is usually simpler and faster than having the parent or main thread call accept and pass the descriptor to the child or thread.
- Having all child processes or threads block on the same accept call is preferable to blocking on the same select call.
- Using threads is usually much faster than using processes.
| Error | Description |
|---|---|
| EADDRINUSE | Address already in use |
| ECONNREFUSED | This is a hard error. If the response to the client's SYN is RST (reset), it means no process is listening on the specified port. The client returns ECONNREFUSED as soon as it receives RST. RST is a TCP segment sent when an error occurs. Three conditions for RST: 1. SYN to a port with no listening server 2. TCP wants to cancel an existing connection 3. TCP receives a segment on a nonexistent connection |
| ETIMEDOUT | TCP client did not receive a response to the SYN segment. |
destination unreachable |
This is a soft error. The client kernel saves this message and continues to send SYNs at intervals. If no response is received after a specified time (4.4BSD: 75s), the saved message (ICMP error) is returned as EHOSTUNREACH or ENETUNREACH. Two possible cases: 1. No route to the remote system in the local routing table. 2. connect returns immediately. |
For TCP connection timeout:
- Use Asynchronous Methods;
- Implement Error Handling;
- Graceful Closure & Reconnection.
[1] (US) W. Richard Stevens, (US) Bill Fenner, (US) Andrew M Rudoff. Unix Network Programming Volume 1: The Sockets Networking API. 3rd Edition
[2] (US) Anthony Jones, Jim Ohlund. Windows Network Programming. 2nd Edition





