[os] Network Programming

Open Systems Interconnection (OSI) Reference Model

-- the ISO proposal for the standardization of various protocols
in computer networks

-- a seven-layer protocol stack:

CLIENT SERVER


Application (e.g., HTTP) <=> Application
(Presentation) (Presentation)
(Session) (Session)
Transport (e.g., TCP, UDP) <
=> Transport
Network (e.g., IP) <
===> Network
(Data Link) (Data Link)
Physical (e.g., Ethernet) <
> Physical

TCP vs. UDP

Transmission Control Protocol (TCP)
-- connection-oriented
-- reliable protocol (re-send missing packets; sequencing; error checking)
-- overhead

User Datagram Protocol (UDP)
-- connection-less
-- unreliable protocol (no re-sending missing/dropped datagrams)
-- low overhead

Socket

  • UDP server socket example:

  • TCP (connection oriented) server socket example:

socket() -- create the endpoint.
bind()         bind the listening port.
listen()        identify it as a TCP listener - can call accept() for incoming client connection requests

while(1){ 

    accept()             // assign different socket descriptors for different request
    recv()/send()
    read()/write()

    close()

}

  • TCP (connection oriented) client socket example:
socket()
connect()

recv()/send()
read()/write()

close()

Basic functions

 #include <sys/types.h>    
 #include <sys/socket.h>

 int socket(int domain, int type, int protocol);    

sockets-based communication can be connection-oriented(TCP) or connection-less(UDP)

socket() creates an endpoint for communication, and returns a file descriptor that refers to that endpoint.

The file descriptor returned by a successful call will be the lowest-numbered file descriptor not currently open for the process.

On success, a file descriptor for the new socket is returned. On error, -1 is returned.

  • send
#include <sys/types.h>
#include <sys/socket.h>

       ssize_t send(int sockfd, const void *buf, size_t len, int flags);

       ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);

       ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);

The send() call may be used only when the socket is in a connected state (so that the intended recipient is known).

If the message is too long to pass atomically through the underlying protocol, the error EMSGSIZE is returned, and the message is not transmitted.

No indication of failure to deliver is implicit in a send(). Locally detected errors are indicated by a return value of -1.

When the message does not fit into the send buffer of the socket, send() normally blocks,

On success, these calls return the number of bytes sent. On error, -1 is returned, and errno is set appropriately.

  • receive

(man page content)

#include <sys/types.h>
#include <sys/socket.h>

       ssize_t recv(int sockfd, void *buf, size_t len, int flags);

       ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

       ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

The recv(), recvfrom(), and recvmsg() calls are used to receive messages from a socket.
They may be used to receive data on both connectionless and connection-oriented sockets.

All three calls return the length of the message on successful completion.
If a message is too long to fit in the supplied buffer, excess bytes may be discarded depending on the type of socket the message is received from.

If no messages are available at the socket, the receive calls wait for a message to arrive, unless the socket is nonblocking (see fcntl(2)), in which case the value -1 is returned and the external variable errno is set to EAGAIN or EWOULDBLOCK.

  • accept (multi-thread socket)
 #include <sys/types.h>          /* See NOTES */
 #include <sys/socket.h>

       int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

       #define _GNU_SOURCE             /* See feature_test_macros(7) */
       #include <sys/socket.h>

       int accept4(int sockfd, struct sockaddr *addr,
                   socklen_t *addrlen, int flags);

used with connection-based socket types (SOCK_STREAM, SOCK_SEQPACKET)
It extracts the first connection request on the queue of pending connections for the listening socket, sockfd, creates a new connected socket, and returns a new file descriptor referring to that socket.
The newly created socket is not in the listening state.

If no pending connections are present on the queue, and the socket is not marked as nonblocking, accept() blocks the caller until a connection is present.

In order to be notified of incoming connections on a socket, you can use select(2), poll(2), or epoll(7)

On success, these system calls return a nonnegative integer that is a file descriptor for the accepted socket. On error, -1 is returned,

  • listen

  • bind

  • select

( file descriptor streams: FD_ZERO(), FD_SET() )

 #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

       int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);

       void FD_CLR(int fd, fd_set *set);
       int  FD_ISSET(int fd, fd_set *set);
       void FD_SET(int fd, fd_set *set);
       void FD_ZERO(fd_set *set);

select() and pselect() allow a program to monitor multiple file descriptors, waiting until one or more of
the file descriptors become "ready" for some class of I/O operation (e.g., input possible). A file
descriptor is considered ready if it is possible to perform a corresponding I/O operation

  • htons
#include <arpa/inet.h>

       uint32_t htonl(uint32_t hostlong);

       uint16_t htons(uint16_t hostshort);

       uint32_t ntohl(uint32_t netlong);

       uint16_t ntohs(uint16_t netshort);

Server

Server types:

(request handling)

  • fork-based

  • fork-based with pre-forked processes

  • thread-based

  • thread-based with pre-threaded

  • select-based (single process)

posted @ 2019-03-28 13:48  gooey  阅读(202)  评论(0编辑  收藏  举报