1. Structure address
1.1. Struct sockaddr{}
1 2 3 4 5 | <span class="token keyword">struct</span> <span class="token class-name">sockaddr</span> <span class="token punctuation">{</span> <span class="token keyword">unsigned</span> <span class="token keyword">short</span> sa_family <span class="token punctuation">;</span> <span class="token comment">// address family, AF_xxx</span> <span class="token keyword">char</span> sa_data <span class="token punctuation">[</span> <span class="token number">14</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token comment">// 14 bytes of protocol address</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> |
This structure is used most of the system calls in part 2, in which:
- sa_family is the address family, has the form AF_xxxx, mainly we use AF_INET
- sa_data[]: store destination address and port
1.2. Struct sockaddr_in{}
1 2 3 4 5 6 7 | <span class="token keyword">struct</span> <span class="token class-name">sockaddr_in</span> <span class="token punctuation">{</span> <span class="token keyword">short</span> <span class="token keyword">int</span> sin_family <span class="token punctuation">;</span> <span class="token comment">// Address family</span> <span class="token keyword">unsigned</span> <span class="token keyword">short</span> <span class="token keyword">int</span> sin_port <span class="token punctuation">;</span> <span class="token comment">// Port number</span> <span class="token keyword">struct</span> <span class="token class-name">in_addr</span> sin_addr <span class="token punctuation">;</span> <span class="token comment">// Internet address</span> <span class="token keyword">unsigned</span> <span class="token keyword">char</span> sin_zero <span class="token punctuation">[</span> <span class="token number">8</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token comment">// Same size as struct sockaddr</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> |
1 2 3 4 5 | <span class="token comment">// Internet address (a structure for historical reasons)</span> <span class="token keyword">struct</span> <span class="token class-name">in_addr</span> <span class="token punctuation">{</span> <span class="token keyword">unsigned</span> <span class="token keyword">long</span> s_addr <span class="token punctuation">;</span> <span class="token comment">// that's a 32-bit long, or 4 bytes</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> |
As a parallel structure to struct sockaddr{}, because storing and retrieving data in struct sockaddr{} is quite complicated, we use this structure.
For some funcs that require the above structure, you can use the sockaddr_in structure and then proceed to cast.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token keyword">int</span> sockfd <span class="token punctuation">;</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr_in</span> my_addr <span class="token punctuation">;</span> sockfd <span class="token operator">=</span> <span class="token function">socket</span> <span class="token punctuation">(</span> PF_INET <span class="token punctuation">,</span> SOCK_STREAM <span class="token punctuation">,</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// do some error checking!</span> my_addr <span class="token punctuation">.</span> sin_family <span class="token operator">=</span> AF_INET <span class="token punctuation">;</span> <span class="token comment">// host byte order</span> my_addr <span class="token punctuation">.</span> sin_port <span class="token operator">=</span> <span class="token function">htons</span> <span class="token punctuation">(</span> MYPORT <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// short, network byte order</span> my_addr <span class="token punctuation">.</span> sin_addr <span class="token punctuation">.</span> s_addr <span class="token operator">=</span> <span class="token function">inet_addr</span> <span class="token punctuation">(</span> <span class="token string">"10.12.110.57"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">memset</span> <span class="token punctuation">(</span> <span class="token operator">&</span> <span class="token punctuation">(</span> my_addr <span class="token punctuation">.</span> sin_zero <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token string">'�'</span> <span class="token punctuation">,</span> <span class="token number">8</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// zero the rest of the struct</span> <span class="token comment">// int bind(int sockfd, struct sockaddr *my_addr, int addrlen); </span> <span class="token function">bind</span> <span class="token punctuation">(</span> sockfd <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr</span> <span class="token operator">*</span> <span class="token punctuation">)</span> <span class="token operator">&</span> my_addr <span class="token punctuation">,</span> <span class="token keyword">sizeof</span> <span class="token punctuation">(</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
1.3. Structure hostent{}
Host data storage structure, mainly used in converting between ip address and host (DNS), used in part 4 – Converting between host name and IP address. Featured are the following two functions:
struct hostent* gethostbyname(const char* hostname)
struct hostent* gethostbyaddr(const char* addr, size_t len, int family)
1 2 3 4 5 6 7 8 | <span class="token keyword">struct</span> <span class="token class-name">hostent</span> <span class="token punctuation">{</span> <span class="token keyword">char</span> <span class="token operator">*</span> h_name <span class="token punctuation">;</span> <span class="token comment">/* official name of host */</span> <span class="token keyword">char</span> <span class="token operator">*</span> <span class="token operator">*</span> h_aliases <span class="token punctuation">;</span> <span class="token comment">/* alias list */</span> <span class="token keyword">int</span> h_addrtype <span class="token punctuation">;</span> <span class="token comment">/* host address type */</span> <span class="token keyword">int</span> h_length <span class="token punctuation">;</span> <span class="token comment">/* length of address */</span> <span class="token keyword">char</span> <span class="token operator">*</span> <span class="token operator">*</span> h_addr_list <span class="token punctuation">;</span> <span class="token comment">/* list of addresses */</span> <span class="token punctuation">}</span> |
2. Data processing
2.1. Convert between host byte and network byte
Data is stored in 2 types Big-endian and Little-endian.
In socket programming, there are two names for storing data, Host byte order and Network byte order (IP), corresponding to Little-endian and Big-endian. Use Network byte order for data that needs to be transmitted through different servers. So need to convert between these two data types by the following functions:
- htons() — “Host to Network Short”
- htonl() — “Host to Network Long”
- ntohs() — “Network to Host Short”
- ntohl() — “Network to Host Long”
In which Short performs conversion with type 2 bytes (using conversion for port), Long is 4 bytes (using conversion for network).
For example, I have port 64, which needs to be stored in the sin_port variable in the struct sockaddr_sin
, and of course needs to be stored in the Network byte order form because this data is being transmitted.
64 has a hex value of 0x40, or in 2-byte form it is written as 0x0040. Perform the conversion sin_addr = htons(64), this function converts from little to big, so its hex value will be 0x4000 and has a value of 16384. That’s why when I run the following program it will be terminated The result is 16384. In simpler terms, both conversion types are byte inversions, but we have two different funcs to understand the conversion type.
2.2. Convert host string to host address and vice versa
inet_addr()
1 2 3 4 5 6 7 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/socket.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><netinet/in.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><arpa/inet.h></span></span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr_in</span> my_addr my_addr <span class="token punctuation">.</span> sin_addr <span class="token punctuation">.</span> s_addr <span class="token operator">=</span> <span class="token function">inet_addr</span> <span class="token punctuation">(</span> <span class="token string">"192.168.1.1"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token operator">=</span> <span class="token operator">></span> <span class="token number">192.168</span> <span class="token number">.1</span> <span class="token number">.1</span> <span class="token punctuation">(</span> Network byte order <span class="token operator">-</span> Big endian <span class="token punctuation">)</span> |
inet_aton()
1 2 3 4 5 6 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/socket.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><netinet/in.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><arpa/inet.h></span></span> <span class="token keyword">int</span> <span class="token function">inet_aton</span> <span class="token punctuation">(</span> <span class="token keyword">const</span> <span class="token keyword">char</span> <span class="token operator">*</span> cp <span class="token punctuation">,</span> <span class="token keyword">struct</span> <span class="token class-name">in_addr</span> <span class="token operator">*</span> inp <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
This function converts const char *cp
(string address) to numbers-and-dots format, stored in struct in_addr
that we use in struct sockaddr_in
Example:
1 2 3 4 5 6 7 | <span class="token keyword">struct</span> <span class="token class-name">sockaddr_in</span> my_addr <span class="token punctuation">;</span> my_addr <span class="token punctuation">.</span> sin_family <span class="token operator">=</span> AF_INET <span class="token punctuation">;</span> <span class="token comment">// host byte order</span> my_addr <span class="token punctuation">.</span> sin_port <span class="token operator">=</span> <span class="token function">htons</span> <span class="token punctuation">(</span> MYPORT <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// short, network byte order</span> <span class="token function">inet_aton</span> <span class="token punctuation">(</span> <span class="token string">"10.12.110.57"</span> <span class="token punctuation">,</span> <span class="token operator">&</span> <span class="token punctuation">(</span> my_addr <span class="token punctuation">.</span> sin_addr <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">memset</span> <span class="token punctuation">(</span> <span class="token operator">&</span> <span class="token punctuation">(</span> my_addr <span class="token punctuation">.</span> sin_zero <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token string">'�'</span> <span class="token punctuation">,</span> <span class="token number">8</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// zero the rest of the struct </span> |
inet_ntoa
Convert numbers_and_dots to string address
1 2 | <span class="token keyword">char</span> <span class="token operator">*</span> <span class="token function">inet_ntoa</span> <span class="token punctuation">(</span> <span class="token keyword">struct</span> <span class="token class-name">in_addr</span> inp <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
Example
1 2 | string <span class="token operator">*</span> addr <span class="token operator">=</span> <span class="token function">inet_ntoa</span> <span class="token punctuation">(</span> my_addr <span class="token punctuation">.</span> sin_addr <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
3. System calls
Reference source: https://www.gta.ufrj.br/ensino/eel878/sockets/syscalls.html
3.1. Socket()
1 2 3 4 5 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/types.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/socket.h></span> <span class="token comment">//để sử dụng socket()</span></span> <span class="token keyword">int</span> <span class="token function">socket</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> domain <span class="token punctuation">,</span> <span class="token keyword">int</span> type <span class="token punctuation">,</span> <span class="token keyword">int</span> protocol <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
Creates a socket, returns the file descriptor, with the smallest value that has not been used. Equals -1 on failure.
- domain: use PF_INET
- type: SOCK_STREAM or SOCK_DGRAM
- protocol: 0 to automatically select the appropriate protocol
See also by: man socket
3.2. Bind()
When a socket is created, there is no value assigned to the socket (ipaddress, port), bind() is used to do that. See more at man bind
1 2 3 4 5 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/types.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/socket.h></span></span> <span class="token keyword">int</span> <span class="token function">bind</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> sockfd <span class="token punctuation">,</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr</span> <span class="token operator">*</span> my_addr <span class="token punctuation">,</span> <span class="token keyword">int</span> addrlen <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
- sockfd: sock file descriptor
- struct sockaddr *my_addr:
- addrlen : size of address, can use sizeof(struct sockaddr)
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><string.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/types.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/socket.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><netinet/in.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><arpa/inet.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">define</span> <span class="token macro-name">MYPORT</span> <span class="token expression"><span class="token number">3490</span></span></span> <span class="token function">main</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">int</span> sockfd <span class="token punctuation">;</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr_in</span> my_addr <span class="token punctuation">;</span> sockfd <span class="token operator">=</span> <span class="token function">socket</span> <span class="token punctuation">(</span> PF_INET <span class="token punctuation">,</span> SOCK_STREAM <span class="token punctuation">,</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// do some error checking!</span> my_addr <span class="token punctuation">.</span> sin_family <span class="token operator">=</span> AF_INET <span class="token punctuation">;</span> <span class="token comment">// host byte order</span> my_addr <span class="token punctuation">.</span> sin_port <span class="token operator">=</span> <span class="token function">htons</span> <span class="token punctuation">(</span> MYPORT <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// short, network byte order</span> my_addr <span class="token punctuation">.</span> sin_addr <span class="token punctuation">.</span> s_addr <span class="token operator">=</span> <span class="token function">inet_addr</span> <span class="token punctuation">(</span> <span class="token string">"10.12.110.57"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">memset</span> <span class="token punctuation">(</span> <span class="token operator">&</span> <span class="token punctuation">(</span> my_addr <span class="token punctuation">.</span> sin_zero <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token string">'�'</span> <span class="token punctuation">,</span> <span class="token number">8</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// zero the rest of the struct</span> <span class="token comment">// don't forget your error checking for bind():</span> <span class="token function">bind</span> <span class="token punctuation">(</span> sockfd <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr</span> <span class="token operator">*</span> <span class="token punctuation">)</span> <span class="token operator">&</span> my_addr <span class="token punctuation">,</span> <span class="token keyword">sizeof</span> <span class="token punctuation">(</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
3.3. Connect()
Connect to 1 remote server
1 2 3 4 5 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/types.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/socket.h></span></span> <span class="token keyword">int</span> <span class="token function">connect</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> sockfd <span class="token punctuation">,</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr</span> <span class="token operator">*</span> serv_addr <span class="token punctuation">,</span> <span class="token keyword">int</span> addrlen <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
- sockfd: sock file desciptor
- struct sockaddr *serv_addr: Structure to store the connection destination and address
- addrlen: address size, use sizeof(struct sockaddr)
This function will return -1 if an error is encountered.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><string.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/types.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/socket.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><netinet/in.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">define</span> <span class="token macro-name">DEST_IP</span> <span class="token string">"10.12.110.57"</span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">define</span> <span class="token macro-name">DEST_PORT</span> <span class="token expression"><span class="token number">23</span></span></span> <span class="token function">main</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">int</span> sockfd <span class="token punctuation">;</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr_in</span> dest_addr <span class="token punctuation">;</span> <span class="token comment">// will hold the destination addr</span> sockfd <span class="token operator">=</span> <span class="token function">socket</span> <span class="token punctuation">(</span> PF_INET <span class="token punctuation">,</span> SOCK_STREAM <span class="token punctuation">,</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// do some error checking!</span> dest_addr <span class="token punctuation">.</span> sin_family <span class="token operator">=</span> AF_INET <span class="token punctuation">;</span> <span class="token comment">// host byte order</span> dest_addr <span class="token punctuation">.</span> sin_port <span class="token operator">=</span> <span class="token function">htons</span> <span class="token punctuation">(</span> DEST_PORT <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// short, network byte order</span> dest_addr <span class="token punctuation">.</span> sin_addr <span class="token punctuation">.</span> s_addr <span class="token operator">=</span> <span class="token function">inet_addr</span> <span class="token punctuation">(</span> DEST_IP <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">memset</span> <span class="token punctuation">(</span> <span class="token operator">&</span> <span class="token punctuation">(</span> dest_addr <span class="token punctuation">.</span> sin_zero <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token string">'�'</span> <span class="token punctuation">,</span> <span class="token number">8</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// zero the rest of the struct</span> <span class="token comment">// don't forget to error check the connect()!</span> <span class="token function">connect</span> <span class="token punctuation">(</span> sockfd <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr</span> <span class="token operator">*</span> <span class="token punctuation">)</span> <span class="token operator">&</span> dest_addr <span class="token punctuation">,</span> <span class="token keyword">sizeof</span> <span class="token punctuation">(</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
3.4. Listen()
Wait for remote connections to arrive and process
1 2 3 4 5 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/types.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/socket.h></span></span> <span class="token keyword">int</span> <span class="token function">listen</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> sockfd <span class="token punctuation">,</span> <span class="token keyword">int</span> backlog <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
- sockfd: sock file descriptor
- backlog: number of incoming connections on the queue to be processed
Returns fd or the value -1 if an error is encountered
Because the listen() function receives a connection from another host, it is necessary to set the port that we receive. So the process would be:
- socket() => bind() => listen() => accept()
We will talk about the accept() function below.
3.5. Accept()
Accept incoming connection and return a file desciptor (same value as fd of listen), used to send and receive data with 2 func send() and recv().
1 2 3 4 5 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/types.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/socket.h></span></span> <span class="token keyword">int</span> <span class="token function">accept</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> sockfd <span class="token punctuation">,</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr</span> <span class="token operator">*</span> addr <span class="token punctuation">,</span> <span class="token class-name">socklen_t</span> <span class="token operator">*</span> addrlen <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
- sockfd: fd of listen()
- struct sockaddr *addr: pointer to struct sockaddr_in address storage structure
- socklen_t *addrlen: pointer to the storage variable sizeof(struct sockaddr_in)
Returns fd with use for send() and recv() below
Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><string.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/types.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><sys/socket.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">include</span> <span class="token string"><netinet/in.h></span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">define</span> <span class="token macro-name">MYPORT</span> <span class="token expression"><span class="token number">3490</span> </span><span class="token comment">// the port users will be connecting to</span></span> <span class="token macro property"><span class="token directive-hash">#</span> <span class="token directive keyword">define</span> <span class="token macro-name">BACKLOG</span> <span class="token expression"><span class="token number">10</span> </span><span class="token comment">// how many pending connections queue will hold</span></span> <span class="token function">main</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">int</span> sockfd <span class="token punctuation">,</span> new_fd <span class="token punctuation">;</span> <span class="token comment">// listen on sock_fd, new connection on new_fd</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr_in</span> my_addr <span class="token punctuation">;</span> <span class="token comment">// my address information</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr_in</span> their_addr <span class="token punctuation">;</span> <span class="token comment">// connector's address information</span> <span class="token keyword">int</span> sin_size <span class="token punctuation">;</span> sockfd <span class="token operator">=</span> <span class="token function">socket</span> <span class="token punctuation">(</span> PF_INET <span class="token punctuation">,</span> SOCK_STREAM <span class="token punctuation">,</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// do some error checking!</span> my_addr <span class="token punctuation">.</span> sin_family <span class="token operator">=</span> AF_INET <span class="token punctuation">;</span> <span class="token comment">// host byte order</span> my_addr <span class="token punctuation">.</span> sin_port <span class="token operator">=</span> <span class="token function">htons</span> <span class="token punctuation">(</span> MYPORT <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// short, network byte order</span> my_addr <span class="token punctuation">.</span> sin_addr <span class="token punctuation">.</span> s_addr <span class="token operator">=</span> INADDR_ANY <span class="token punctuation">;</span> <span class="token comment">// auto-fill with my IP</span> <span class="token function">memset</span> <span class="token punctuation">(</span> <span class="token operator">&</span> <span class="token punctuation">(</span> my_addr <span class="token punctuation">.</span> sin_zero <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token string">'�'</span> <span class="token punctuation">,</span> <span class="token number">8</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// zero the rest of the struct</span> <span class="token comment">// don't forget your error checking for these calls:</span> <span class="token function">bind</span> <span class="token punctuation">(</span> sockfd <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr</span> <span class="token operator">*</span> <span class="token punctuation">)</span> <span class="token operator">&</span> my_addr <span class="token punctuation">,</span> <span class="token keyword">sizeof</span> <span class="token punctuation">(</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">listen</span> <span class="token punctuation">(</span> sockfd <span class="token punctuation">,</span> BACKLOG <span class="token punctuation">)</span> <span class="token punctuation">;</span> sin_size <span class="token operator">=</span> <span class="token keyword">sizeof</span> <span class="token punctuation">(</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr_in</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> new_fd <span class="token operator">=</span> <span class="token function">accept</span> <span class="token punctuation">(</span> sockfd <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token keyword">struct</span> <span class="token class-name">sockaddr</span> <span class="token operator">*</span> <span class="token punctuation">)</span> <span class="token operator">&</span> their_addr <span class="token punctuation">,</span> <span class="token operator">&</span> sin_size <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
3.6. Send() and Recv()
Send()
1 2 | <span class="token keyword">int</span> <span class="token function">send</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> sockfd <span class="token punctuation">,</span> <span class="token keyword">const</span> <span class="token keyword">void</span> <span class="token operator">*</span> msg <span class="token punctuation">,</span> <span class="token keyword">int</span> len <span class="token punctuation">,</span> <span class="token keyword">int</span> flags <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
- sockfd: fd of the host that wants to send data, can be the fd returned by socket() or accept()
- const void *msg: data to send
- int len: The size of the data in bytes
- int flags: Set the value to 0
The function returns the number of bytes sent, sending all if the number of bytes is less than 1K. Compare the return value with int len to see if the data has been sent and process the rest.
Recv()
Get data sent to
1 2 | <span class="token keyword">int</span> <span class="token function">recv</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> sockfd <span class="token punctuation">,</span> <span class="token keyword">void</span> <span class="token operator">*</span> buf <span class="token punctuation">,</span> <span class="token keyword">int</span> len <span class="token punctuation">,</span> <span class="token keyword">unsigned</span> <span class="token keyword">int</span> flags <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
- sockfd: fd of sender
- void *buf: buffer containing data
- int len: maximum input size
- flags set to 0
The function returns -1 if an error occurs, 0 if the connection is closed and the other value is the number of bytes received
3.7. Close() and shutdown()
Close()
close(sockfd)
- sockfd: fd wants to close the connection, stop sending and receiving data
shutdown()
1 2 | <span class="token keyword">int</span> <span class="token function">shutdown</span> <span class="token punctuation">(</span> <span class="token keyword">int</span> sockfd <span class="token punctuation">,</span> <span class="token keyword">int</span> how <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
- sockfd: fd wants to close the connection
- how: how to close (0-stop receiving, 1-stop sending, 2-stop receiving and sending)
4. Switch between Host name and IP address
5. Error handling in socket
To print errors while connecting or using functions, we use the perror()
and herror()
in the errno.h
library.
For example, when an error returns -1 in the socket() function, we print the error by perror(“socket”); Example:
1 2 3 4 5 | <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> sockfd <span class="token operator">=</span> <span class="token function">socket</span> <span class="token punctuation">(</span> PF_INET <span class="token punctuation">,</span> SOCK_STREAM <span class="token punctuation">,</span> <span class="token number">0</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token operator">-</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">perror</span> <span class="token punctuation">(</span> <span class="token string">"socket"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">exit</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
For the DNS handling functions (in part 4), use the herror function to print the error. Example:
1 2 3 | <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> he <span class="token operator">=</span> <span class="token function">gethostbyname</span> <span class="token punctuation">(</span> <span class="token string">"facebook.com"</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token constant">NULL</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// get the host info </span> <span class="token function">herror</span> <span class="token punctuation">(</span> <span class="token string">"gethostbyname"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |