%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Rychla reference k sitovym socketum
%
%  Martin Bruchanov -- bruxy at regnet dot cz
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%\pdfoutput=1
\documentclass[a4paper, 10pt, pointednumbers]{scrartcl}
\usepackage{czech}
\usepackage{a4wide}
\usepackage{graphics}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{latexsym}
\usepackage{multicol}

% změna okrajů stránky, které jsou standardně 1 palec = 2.54 cm
\evensidemargin 0mm
\oddsidemargin 0mm
\headsep 0mm
\hoffset -18.4mm
\voffset -17.4mm % vrsek
\topmargin 0in 
\headheight 0cm
\textwidth 197mm
\textheight 28.7cm
\footskip 0mm

% Zmena radkovani
\renewcommand{\baselinestretch}{1.0}

% Zmena vzdalenosti
%\newcommand{\itemizespace}{-0.5em}
\newcommand{\itemizespace}{0em}


\pagestyle{empty}

\begin{document} 
\section*{Síťové sockety}
\addtocounter{section}{1}

\begin{multicols}{2}

\begin{description}

\item[TCP] -- před samotnou komunikací se naváže spojení, Všechna odeslaná data
se potvrzují a na konec je nutné spojení ukončit (uzavřít). TCP paket obsahuje
svou hlavičku a samotná data, která přenáší. TCP paket bude vložen do IP
datagramu (jako data IP datagramu) a odeslán.

\item[UDP] -- jedná se  tzv. nespojovanou službu. To znamená, že nedochází k
navázání spojení. Prostě odešleme data na stanovenou IP adresu a daný UDP port
a nevíme, zda data dorazila a zda se nepoškodila nebo nedorazila v jiném
spojení.

\end{description}


\subsection{Funkce pro práci se sockety}

%\begin{verbatim}
%int descriptor, domain, type, protocol;
%decriptor = socket(domain, type, protocol);
%\end{verbatim}

\begin{itemize}\addtolength\itemsep{\itemizespace}
\item Definice formátů adres (\verb|<sys/socket.h>|):
\begin{itemize}\addtolength\itemsep{\itemizespace}
\item \verb|AF_UNIX| -- interní protokol UNIXu, 
\item \verb|AF_INET| -- Internet. adresy,
\item \verb|AF_ISO| -- protokoly ISO.
\end{itemize}

\item Typ socketu:
\begin{itemize}\addtolength\itemsep{\itemizespace}
\item \verb|SOCK_STREAM| -- (TCP) sekvenční, spolehlivá, dvoustranná proudová
komunikace, mechanizmus přenosu \emph{out-of-band}, 
\item \verb|SOCK_DGRAM| -- (UDP) podpora datagramů (nespojované, nespolehlivé zprávy
malé délky).
\end{itemize}

\item Specifikace jména socketu:

\begin{verbatim}
struct sockaddr {
    /* Rodina adres AF_xxx */
    unsigned short sa_family;  
    /* až 14bytová přímá adresa */
    char sa_data[14]; };
\end{verbatim}

\item Volba adresy a portu:
\begin{verbatim}
struct sockaddr_in {
	/* Rodina adres AF_xxx */
    short int          sin_family;  
    /* Číslo portu */ 
     unsigned short int sin_port;    
    /* Internetová adresa */
    struct in_addr     sin_addr;   
    /* nepoužito */
    unsigned char      sin_zero[8]; };
\end{verbatim}

\item Nastavení adresy:

\begin{verbatim}
struct in_addr {
/* 32 bitová adresa */
    unsigned long s_addr; };
\end{verbatim}

\item Pro převod adresy z textového tvaru (192.168.0.1) do binárního tvaru:

\begin{verbatim}
int inet_aton (const char *NAME, 
               struct in_addr *ADDR)

struct in_addr {
   unsigned long int s_addr;
};
\end{verbatim}

\item převod pořadí bytu mezi síťí (big endian, MSB první) a hostem,
např. na x86 je LSB byte první v pořadí (little endian).

\begin{itemize}\addtolength\itemsep{\itemizespace}
\item Host $\rightarrow$ Network:\\
 \verb|uint32_t htonl(uint32_t hostlong)|, \\
 \verb|uint16_t htons(uint16_t hostshort)|.
\item Network $\rightarrow$ Host:\\
 \verb|uint32_t ntohl((uint32_t netlong)|, \\
 \verb|uint16_t ntohs((uint16_t hostshort)|.
\end{itemize}

\item \textbf{socket()} -- tvoří socket daného typu a vrátí
file-descriptor, protokol 0x0, domain \verb|AF_xxx|

\begin{verbatim}
int socket(int domain, int type, int protocol);
\end{verbatim}

\item \textbf{connect()} -- slouží k navazování spojení

\begin{verbatim}
int connect(int sockfd, struct sockaddr
             *serv_addr, int addrlen);
\end{verbatim}

\item \textbf{bind()} --  sváže socket se jménem, v kombinaci s
\texttt{listen()} určí čísla portu, kde server poslouchá

\begin{verbatim}
int bind(int sockfd, struct sockaddr 
         *my_addr, int addrlen);
\end{verbatim}

\item \textbf{listen()} --  zavolat po \texttt{bind()}, slouží ke
konfiguraci pro příjem dat., \texttt{backlog} udává max. počet nepokrytých
spojení ve frontě.

\begin{verbatim}
int listen(int sockfd, int backlog);
\end{verbatim}

\item \textbf{accept()} -- čeká na příchozí spojení, vrátí parametry
prvního spojení ve frontě a nový socket, který slouží ke komunikaci s
druhou stranou. Původní socket \texttt{sockfd} se tak může opět použít
pro čekání na další spojení.

\begin{verbatim}
int accept(int sockfd, void *addr, int *addrlen);
\end{verbatim}

\item \textbf{close(), shutdown()} --  zavírá socket.

\item {\large\bfseries  Posílání zpráv do socketu}

\begin{itemize}\addtolength\itemsep{\itemizespace}
\item \textbf{send()} -- pouze jeli socket spojený, neobsahuje indikaci správného doručení,
s flagem 0 je ekv. \texttt{write()}.
\begin{verbatim}
int send(int s, const void *msg, 
         int len, unsigned int flags);
\end{verbatim}

\item \textbf{sendto()} -- pouze pro \verb|SOCK_STREAM| 
\begin{verbatim}
int  sendto(int  s, const void *msg, int len, 
            unsigned int flags, 
            const struct sockaddr *to, 
			int tolen);
\end{verbatim}

Definice struktury \texttt{msghdr}:

\begin{verbatim}
struct msghdr {
 /* optional address */
    void * msg_name;
/* size of address */
    socklen_t  msg_namelen;  
/* scatter/gather array */
    struct iovec * msg_iov;  
/* # elements in msg_iov */
    size_t msg_iovlen;     
/* ancillary data, see below */
    void * msg_control;     
/* ancillary data buffer len */
    socklen_t  msg_controllen; 
/* flags on received message */
    int  msg_flags;  
};
\end{verbatim}

\item \textbf{sendmsg()} --

\begin{verbatim}
int sendmsg(int s, const struct msghdr *msg,  
            unsigned int flags);
\end{verbatim}

\item \textbf{write()} -- systémová funkce \verb|<unistd.h>|

\begin{verbatim}
ssize_t write(int fd, const void *buf,
               size_t count);
\end{verbatim}

\item Hodnoty parametry \texttt{flags}:
	\begin{itemize}\addtolength\itemsep{\itemizespace}
		\item \verb|MSG_OOB| -- zpracuj out-of-band data
		\item \verb|MSG_DONTROUTE| -- obejdi routing, použij přímé rozhraní
	\end{itemize}
\end{itemize}

\item {\large\bfseries Příjem zprávy ze socketu}
	\begin{itemize}\addtolength\itemsep{\itemizespace}
		\item \textbf{recv()} -- čtení dat bez odstranění z fronty
\begin{verbatim}
ssize_t recv(int s, void *buf, 
             size_t len, int flags);
\end{verbatim}
		\item \textbf{recvfrom()} --
\begin{verbatim}
ssize_t  recvfrom(int  s,  void *buf, 
                  size_t len, int flags, struct
                  sockaddr *from,  
                  socklen_t *fromlen);
\end{verbatim}
		\item \textbf{recvmsg()} --
\begin{verbatim}
ssize_t recvmsg(int s, struct msghdr *msg, 
                int flags);
\end{verbatim}
		
		\item \textbf{read()} -- systémová funkce \verb|<unistd.h>|,
		čte data bez odstranění z fronty

\begin{verbatim}
ssize_t read(int fd, void *buf, size_t count);
\end{verbatim}		 
	\end{itemize}

\item Chybové návraty

\begin{itemize}\addtolength\itemsep{\itemizespace}
	\item EBADF -- špatný descriptor,
	\item ECONNREFUSED -- odmítnutí spojení,
	\item ENOTCONN -- nepřipojený socket,
	\item ENOTSOCK -- argument není socket,
	\item EAGAIN -- čas vypršel před doručením,
	\item EINTR -- příjem přerušen,
	\item EFAULT -- RX ukazatel mimo adresový prostor,
	\item EINVAL -- vložen špatný argument,
	\item ENOMEM -- nelze alokovat paměť pro \texttt{recvmsg}.
	
\end{itemize}

\end{itemize}

\subsection{Překlad doménových jmen}

\begin{itemize}\addtolength\itemsep{\itemizespace}
\item Definice funkcí \verb|<netdb.h>|

\item Struktura \texttt{hostent} pro char. vzdáleného
počítače

\begin{verbatim}
struct hostent {
/* Řetězec s názvem počítače */
   char   *h_name;      
/* Ukazatel na pole aliasu, ukončený NULL */ 
   char  **h_aliases;   
/* Typ adresy, např. AF_INET */
      int     h_addrtype;   
/* Dělka adresy v bytech */
      int     h_length;     
/* Ukazatel na pole ukazatelů ukončené NULL,
   ukazatel obsahuje adresu pole typu char
   délky h_length, obsahující adresu v síťovém
   pořadí */
     char  **h_addr_list  
};
\end{verbatim}

\item \textbf{gethostbyname()} -- vratí informace o zadaném
doménovém jméně.

\begin{verbatim}
struct hostent *gethostbyname(const char *name);
\end{verbatim}

\item \textbf{gethostbyaddr()} -- vráti info o zazané adrese

\begin{verbatim}
struct hostent *gethostbyaddr(const char *addr, 
                              int len, int type);
\end{verbatim}

%\item \textbf{sethostent()} -- 
%\begin{verbatim}
%void sethostent(int stayopen);
%\end{verbatim}

%\item \textbf{endhostent()} -- 

%\begin{verbatim}
%void endhostent(void);
%\end{verbatim}

%\item \textbf{herror()} -- 
%\begin{verbatim}
%void herror(const char *s);
%\end{verbatim}

\item Struktura \texttt{protent}

\begin{verbatim}
struct protoent {
    char *p_name; /* official protocol name */
    char **p_aliases; /* alias list */
    int p_proto; /* protocol number */
};
\end{verbatim}

\item \textbf{getprotobyname(), getprotobynumber()} -- vrátí \texttt{protent} pro
daný řádek z \texttt{/etc/protocols} pro daný protokol nebo jeho číslo.

\begin{verbatim}
struct protoent *getprotobyname(const char *name);
struct protoent *getprotobynumber(int proto);
\end{verbatim}

%struct protoent *getprotoent(void);
%struct servent *getservent(void);

\item Struktura \texttt{servent}

\begin{verbatim}
struct servent {
  char *s_name;     /* official service name */
  char **s_aliases; /* alias list */
  int  s_port;      /* port number */
  char *s_proto;    /* protocol to use */ };
\end{verbatim}


\item \textbf{getservbyname(), getservbyport()} -- vrací strukturu
\texttt{servent} pro konkrétní službu nebo číslo z \texttt{/etc/services}

\begin{verbatim}
struct servent *getservbyname(const char *name, 
                              const char *proto);
struct servent *getservbyport(int port, 
                              const char *proto);
\end{verbatim}
\end{itemize}

\subsection{Kompilace}

\begin{itemize}\addtolength\itemsep{\itemizespace}

\item Doporučené hlavičkové soubory: \texttt{<stdio.h> <stdlib.h>, <unistd.h>,
<netinet/in.h>, <netdb.h>,\\ <sys/socket.h>, <string.h>}

\item Kompilace na GNU/Linux:

\begin{verbatim}
gcc -Wall -o program zdrojak.c
\end{verbatim}

\item Kompilace na Solaris vyžaduje doplnění 
knihoven:
\begin{verbatim}
gcc -Wall -lnsl -lsocket -o program zdrojak.c
\end{verbatim}

\item Příklad \texttt{Makefile}
\begin{verbatim}
all: program

program.o: zdrojak.c
   gcc -c -o program.o zdrojak.c

program: program.o
   gcc -Wall -o program program.o
\end{verbatim}
\end{itemize}

\end{multicols}
\end{document}


