Linux网络(二)网络编程函数

424阅读 0评论2012-03-06 xbjpkpk
分类:

 listen system call

  listen()监听套接字上的连接

        1.int listen(int sockfd, int backlog) ;

        2.被动监听的socket

        3.需要在此前调用bind()函数,否则由系统指定一个随机的端口

        4.成功返回0,失败返回-1

    连接队列

        1.一个新的Client的连接请求先被放在连接队列中,等待Server程序调用accept函数接受连接请求

        2.backlog指的就是接收队列的长度,亦即Server程序调用accept函数之前最大允许的连接请求数,多余的连接请求将被拒绝

 

accept system call

  accept()函数将响应连接请求,建立连接

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

   2.accept缺省是阻塞函数,阻塞直到有连接请求

   3.sockfd:被动(监听)socket描述符

   4.如果成功,返回一个新的socket描述符(connected socket descriptor)来描述该连接。这个连接用来与特定的Client交换信息,原来的socket描述符继续保持非连接监听。如果失败则返回-1

   5.addr将在函数调用后被填入连接对方的地址信息,如对方的IP、端口等。

 

connect system call

    客户端使用connect()函数连接到主机

        int connect(int sockfd, struct sockaddr * servaddr, int addrlen) ;

    主动的socket

    servaddr是事先填写好的结构,ServerIP和端口都在该数据结构中指定。

    通常connect将阻塞直到服务器响应为止。

    成功返回0,失败返回-1

 

send/recv

       面向连接的socket数据通讯

           int send(int sockfd, const void * msg, size_t len, int flag ) ;

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

           数据发送/接收函数,成功返回实际发送/接收的字节数,失败返回-1

       write/read比较

           ssize_t write(int fd, const void * buf, size_t count);

           ssize_t read(int fd, void *buf, size_t count);

       flag:

           1.send:MSG_OOB, MSG_DONTROUTE,MSG_DONTWAIT,MSG_NOSIGNAL, ...

           2.recv:MSG_OOB, MSG_PEEK,MSG_WAITALL,MSG_NOSIGNAL,…

             OOB(out-of-band),一般用于紧急特殊数据。

 

sendto/recvfrom

       面向数据报的socket通讯sendto/recvfrom

        int sendto(int sockfd, const void *msg, size_t len, int flags, const

            struct sockaddr *to, socketlen_t tolen) ;

        int recvfrom(int sockfd, void *buf, size_t len, int flags, struct

            sockaddr *from, socklen _t *fromlen);

 

close&shutdown

        close关闭套接字

          1.int close(int sockfd);

        shutdown按指定方式关闭套接字

          1.int shutdown(int sockfd, int how);

          2.how:SHUT_RD,SHUT_WR,SHUT_RDWR

        shutdown直接对TCP连接进行操作,close只是对套接字描述符操作。

 

getsockopt&setsockopt

       检查与修改套接字选项

         int getsockopt(int socket, int level, int optname,

                         void *optval, socklent *optlen-ptr)

         int setsockopt(int socket, int level, int optname,

                         void *optval, socklent optlen)

       level为操作级别,当为普通socket级时,设为SOL_ SOCKET,否则设为操作控制选项对应的协议号,如TCP选项为IPPROTO_TCPIP选项为IPPROTO_IP

 

Host name and address conversions

    Files:

        1./etc/resolv.conf, /etc/hosts

    Functions

        #include

        struct hostent *gethostbyname(const char *name);

        struct hostent *gethostbyaddr(const char *addr, size_t len, int format);

    struct hostent

        struct hostent {

             char *h_name;   /* official name of host */

             char **h_aliases;   /* alias list * /

             int h_addrtype;     /* host address type, AF_INET/ AF _INET6 */

            int h_length;     /* length of address */

            char **h_addr_list; /* list of addresses */

         };

 

Service name and port number conversions

    File:

        1./etc/services

    Functions:

        #include

        struct servent *getservbyname(const char *name, const char *proto);

        struct servent *getservbyport(int port, const char *proto) ;

    struct servent

        struct servent {

               char *s_name ;    /* official service name */

               char **s_aliases ; /* alias list */

               int s_port;        /* port number */

               char *s_proto;     /* protocol to use */

         };

 

Multi-process server

Non-block mode

    阻塞与非阻塞方式的比较

        1.errno - EWOULDBLOCK

     非阻塞的实现

        int flags;

        if((flags=fcntl(sock_fd, F_GETFL ,0))< 0)

            err_sys();

        flags|=O_NONBLOCK;

        if(fcntl(sock_fd, F_SETFL, flags)<0)

            err_sys();

 

Signal-driven I/O

    用于接收紧急数据

        1.带外数据

        2.SIGURG,SIGIO

    实现

        1.fcntl(conn_fd, F_SETOWN, getpid());

        2.sigaction

 

I/O multiplexing

    基本思想

        先构造一张有关描述符的表,然后调用一个函数(select),该函数到这些描述符中的一个已准备好进行I/O   时才返回,返回时告诉进程哪个描述符已准备好进行I/O.

     select:synchronous I/O multiplexing.

        #include

        int select(int n, fd _set *readfds, fd_set *writefds, fd_set *exceptfds,

                    struct timeval *timeout);

        FD_ZERO(fd_set * set);

        FD_SET(int fd, fd_set *set);

        FD_CLR(int fd, fd_set *set);

        FD_ISSET(int fd, fd_set *set);

 

xinetd 启动服务的过程

     xinetd启动时读取/etc/xinetd目录中的文件(早期版本为/etc/inetd文件),根据其中的内容给所有允许启动的服务创建一个指定类型的套接口,并将套接口放入select()中的描述符集合中。

    对每个套接口绑定bind(),所用的端口号和其它参数来自/etc/xinetd目录下每个服务的配置文件。

    如果是TCP套接口就调用函数listen(),等待用户连接。如果是UDP套接口,就不需调用此函数。

    所有套接口建立后,调用函数select()检查哪些套接口是准备好的。

    select()返回TCP套接口,就调用accept()接收这个连接。如果为UDP,就不需调用此函数。

    xinetd调用fork()创建子进程,由子进程处理连接请求。

        1.子进程关闭所有其它描述符,只剩下套接口描述符。这个套接口描述符对于TCPaccept()返回的套接口,对于UDP为最初建立的套接口。然后子进程连续三次dup()函数,将套接口描述符复制到012,它们分别对应标准输入、标准输出和标准错误输出,并关闭套接口描述符。

        2. 子进程查看/etc/xinetd下文件中的用户,如果不是root用户,就用调用命令setuidsetgid将用户ID和组ID改成文件中指定的用户。

    对于TCP套接口,与用户交流结束后父进程需要关闭已连接套接口。父进程重新处于select()状态,等待下一个可读的套接口。

    最后调用配置文件中指定的外部服务程序,外部程序启动后就可与用户进行信息传递了。

上一篇:嵌入式Linux网络驱动程序的开发及实现原理
下一篇:嵌入式学习路线