• 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/

     

  • 相关阅读:
    Asp.Net2.0中的缓存
    webpartzone无法显示最小化和关闭按钮?
    TransactionScope分布式事务和非分布式事务
    JS获取GET参数的两种方法
    js 文件上传下载功能
    android动态设置布局LayoutInflater的使用详解
    Eclipse大括号换行显示
    Java强引用、 软引用、 弱引用、虚引用(转载)
    Android扭曲图像(水面落叶壁纸初步实现)
    win7系统自带的屏幕录制软件
  • 原文地址:https://www.cnblogs.com/westfly/p/2173277.html
Copyright © 2020-2023  润新知