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'ssocketaddress.sin6_addr = in6addr_any;      // Listen on any ipv6 addresssocketaddress.sin6_family = AF_INET6;       // Address Family AF_INET6 is requiredsocketaddress.sin6_port = htons(8000);      // Listen on port 8000, we have to convert the integer to network short | 
Creating the socket
| 1 | intsocket(intdomain, inttype, intprotocol); | 
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 | intbind(intsocket, conststructsockaddr *address, socklen_t address_len); | 
socket – Socket descriptor
address – Socket address (address, port, family…)
address_len – Structure address size
Listen on socket
| 1 | intlisten(intsocket, intbacklog); | 
socket – Socket descriptor
backlog – Maximum pending connections on queue
Returns
0 – OK
-1 – Error
Wait for socket to be ready
| 1 | intselect(intnfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict errorfds, structtimeval *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 | intaccept(intsocket, structsockaddr *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>voidnewConnectionHandler(intsockd){        charbuffer[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");}intmain(intargc, char*argv[]){        intsockd,newsockd,tmpint;        structsockaddr_in6 socketaddress;        fd_set descriptorslist;        structtimeval 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");                return1;        }        // Bind socket sockfd on socketaddress        if(bind(sockd, (structsockaddr *)&socketaddress, sizeof(socketaddress)) != 0){                perror("Unable to bind socket");                return1;        }        // Listen on socket, queue up to 10 connections        if(listen(sockd,10) != 0){                perror("Unable to listen on socket ");                return1;        }        // 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;                        case0:                                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,(structsockaddr *)&socketaddress, &tmpint));                                        exit(0);                                }                }        }} | 
http://www.silviosilva.com/2009/07/15/berkeley-socket-api-creating-a-tcpip-server-in-c/
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号