Berkeley Socket API – Creating a TCP/IP Server in C
Berkeley Socket API – Creating a TCP/IP Server in C
Programming Languages
C
API
Berkeley Socket API
What are sockets?
“In computer networking, an Internet socket (or commonly, a network socket or socket) is the endpoint of a bidirectional inter-process communication flow across an Internet Protocol-based computer network, such as the Internet. Internet sockets (in plural) are an application programming interface (API) application program and the TCP/IP stack, usually provided by the operating system. Internet sockets constitute a mechanism for delivering incoming data packets to the appropriate application process or thread, based on a combination of local and remote IP addresses and port numbers. Each socket is mapped by the operational system to a communicating application process or thread.”
in Wikipedia
Data Structure used to store socked details
1
2
3
4
5
6
7
|
struct sockaddr_in6 { u_char sin6_len; // length of this structure u_char sin6_family; // AF_INET6 u_int16m_t sin6_port; // Transport layer port # u_int32m_t sin6_flowinfo; // IPv6 flow information struct in6_addr sin6_addr; // IPv6 address }; |
Data Structure used to store a time value
Used on ‘select’ for timeouts
1
2
3
4
|
struct sockaddr_in6 { long int tv_sec // This represents the number of whole seconds of elapsed time. long int tv_usec // The rest of the elapsed time (microseconds) }; |
Filling the socket address
1
2
3
4
5
6
|
struct sockaddr_in6 socketaddress; memset(&socketaddress,0,sizeof(socketaddress)); // Fill the structure with zero's socketaddress.sin6_addr = in6addr_any; // Listen on any ipv6 address socketaddress.sin6_family = AF_INET6; // Address Family AF_INET6 is required socketaddress.sin6_port = htons(8000); // Listen on port 8000, we have to convert the integer to network short |
Creating the socket
1
|
int socket( int domain, int type, int protocol); |
domain
AF_UNIX – UNIX internal protocols
AF_INET – ARPA Internet protocols
AF_ISO – ISO protocols
AF_NS – Xerox Network Systems protocols
AF_IMPLINK – IMP host at IMP link layer
Type
SOCK_STREAM – provides sequenced, reliable, two-way connection based byte streams
SOCK_DGRAM – connectionless, unreliable messages of a fixed (typically small) maximum length
SOCK_RAW – sockets provide access to internal network protocols and interfaces
SOCK_SEQPACKET – provide a sequenced, reliable, two-way connection-based data transmission path for datagrams of fixed maximum length
SOCK_RDM – Not implemented
Returns
0 – Error
1+ – Socket descriptor
Bind the socket
1
|
int bind( int socket, const struct sockaddr *address, socklen_t address_len); |
socket – Socket descriptor
address – Socket address (address, port, family…)
address_len – Structure address size
Listen on socket
1
|
int listen( int socket, int backlog); |
socket – Socket descriptor
backlog – Maximum pending connections on queue
Returns
0 – OK
-1 – Error
Wait for socket to be ready
1
|
int select( int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict errorfds, struct timeval *restrict timeout); |
ndfs – number of descriptors
readfds – ‘set’ of descriptors to read from
writefds – ‘set’ of descriptors to write to
errorfds – ‘set’ of descriptors to expect errors from
timeout – time to wait before giveout a timeout
Returns
1+ – Socket descriptor
0 – Timeout
-1 – Error
Accepting an incoming connection
1
|
int accept( int socket, struct sockaddr *restrict address, socklen_t *restrict address_len); |
socket – Socket descriptor
address – Socket address (address, port, family…)
address_len – Structure address size
Returns
1+ – Descriptor of the new socket
-1 – Error
Read and write from a socket
It works exactly like when we’re reading from a file, pipe, etc.
Read from socket
1
|
read(sockd, &buffer, 100); |
Write to socket
1
|
write(sockd, &buffer, strlen (buffer)); |
The server code revealed
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
#include <stdio.h> #include <sys/types.h> #include <fcntl.h> #include <sys/socket.h> #include <sys/param.h> #include <sys/stat.h> #include <unistd.h> #include <netinet/in.h> #include <string.h> #include <stdlib.h> void newConnectionHandler( int sockd){ char buffer[100]; if (read(sockd, &buffer, 100) < 1) perror ( "Unable to read from socket" ); if (write(sockd, &buffer, strlen (buffer)) < 1) perror ( "Unable to write on socket" ); } int main( int argc, char *argv[]) { int sockd,newsockd,tmpint; struct sockaddr_in6 socketaddress; fd_set descriptorslist; struct timeval timeout; memset (&socketaddress,0, sizeof (socketaddress)); socketaddress.sin6_addr = in6addr_any; socketaddress.sin6_family = AF_INET6; socketaddress.sin6_port = htons(8000); // Create the socket - inet6 - stream - tcp if ((sockd = socket(AF_INET6, SOCK_STREAM,0))<1){ perror ( "Unable to create socket" ); return 1; } // Bind socket sockfd on socketaddress if (bind(sockd, ( struct sockaddr *)&socketaddress, sizeof (socketaddress)) != 0){ perror ( "Unable to bind socket" ); return 1; } // Listen on socket, queue up to 10 connections if (listen(sockd,10) != 0){ perror ( "Unable to listen on socket " ); return 1; } // Clear the socket 'set' FD_ZERO(&descriptorslist); // Add sockd to fdread 'set' FD_SET(sockd, &descriptorslist); while (1){ // Set socket timeout to 1.1secs, timeout values change after each select so it has to be inside the loop timeout.tv_sec = 1; timeout.tv_usec = 100; switch (select(32, &descriptorslist, NULL, NULL, &timeout)){ case -1: perror ( "And error has ocurred" ); break ; case 0: printf ( "Timeout" ); break ; default : // Default, more than 0, number of descriptors on 'descriptorslist' ready tmpint = sizeof (socketaddress); // We fork an handler for the new connection (a new socket is passed as argument) if (fork() == 0) // The above line is executed on child, where fork() == 0 { newConnectionHandler(accept(sockd,( struct sockaddr *)&socketaddress, &tmpint)); exit (0); } } } } |
http://www.silviosilva.com/2009/07/15/berkeley-socket-api-creating-a-tcpip-server-in-c/