zoukankan      html  css  js  c++  java
  • 网络之Socket详解

    网络之Socket详解

    1.什么是Socket?

    Socket本质上还是文件,因为Linux上一切皆文件。Socket也有对应的文件描述符(fd)。文件描述符相关的参考另外一篇博客。

    http://blog.csdn.net/weililansehudiefei/article/details/78113082

    在这里简单就认为,它是对应着一个文件的,就可以。

    Socket位于TCP/IP之上,通过Socket可以方便的进行通信连接。对外屏蔽了复杂的TCP/IP。

    2.Socket连接详解

    Socket连接建立的基本过程如下:

    接下来就按照这个流程进行

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

    该方法 返回一个socket_fd,即socket的文件描述符

    domain:说明我们网络程式所在的主机采用的通讯协族(AF_UNIX和AF_INET等). AF_UNIX只能够用于单一的Unix系统进程间通信,而AF_INET是针对Internet的,因而能允许在远程主机之间通信(当我们 man socket时发现 domain可选项是 PF_*而不是AF_*,因为glibc是posix的实现所以用PF代替了AF,不过我们都能使用的).

    type:我们网络程式所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM等)SOCK_STREAM表明我们用的是TCP协议,这样会提供按顺序的,可靠,双向,面向连接的比特流. SOCK_DGRAM 表明我们用的是UDP协议,这样只会提供定长的,不可靠,无连接的通信.

    protocol:由于我们指定了type,所以这个地方我们一般只要用0来代替就能了 socket为网络通讯做基本的准备.成功时返回文件描述符,失败时返回-1,看errno可知道出错的周详情况.

    2.int bind(SOCKET socketfd, const struct sockaddr* address, socklen_t address_len);

    sockfd:是由上一步socket调用返回的文件描述符.

    addrlen:是sockaddr结构的长度.

    my_addr:是个指向sockaddr的指针.在<linux/socket.h>中有 sockaddr的定义

           struct sockaddr{

                   unisgned short  as_family;

                   char           sa_data[14];

                   };

    不过由于系统的兼容性,我们一般不用这个头文件,而使用另外一个结构(struct   sockaddr_in)来代替.在<linux/in.h>中有sockaddr_in的定义 

            struct sockaddr_in{

                   unsigned short         sin_family;     

                   unsigned short int      sin_port;

                   struct in_addr          sin_addr;

                   unsigned char          sin_zero[8];

    我们主要使用Internet所以sin_family一般为AF_INET,sin_addr设置为INADDR_ANY表示能和所有的主机通信,sin_port是我们要监听的端口号.sin_zero[8]是用来填充的. bind将本地的端口同socket返回的文件描述符捆绑在一起.成功是返回0,失败的情况和socket相同

    3.int listen(int socketfd,int backlog); 

    ilsten通过socket套接字和该套接字绑定的IP信息在内核开启监听,并且返回监听描述符。此处监听工作交给内核处理,代码本身不阻塞,但内核对应端口一直在做监听工作。同时维护两个队列,一个是请求队列,一个是就绪队列,大小由backlog决定。

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

    接受连接请求,代码默认阻塞。accept实际上是在从内核listen维护的就绪队列中取描述符。accept成功时返回最后的服务器端的文件描述符。重要:这里返回的是一个新的Socket,即socketfd_new.而不是最开始创建的socketfd。用socket_new进行与客户端的通信。

    服务器的一个端口,是只能有一个socket绑定的。新生成的socketfd_new虽然有和处理连接请求的socket一样的ip和端口,但是他门不占用端口。我的理解,就是这些新生成的socketfd_new,没有进行bind的操作,所以没有和内核绑定,所以没出现冲突。而socketfd本质上有五大因素决定(fd,src_ip,src_port,des_ip,des_port)。socket里是存放了双方的ip的。

    所以,accept方法返回的socketfd_new,已经有了双端的ip和端口,那么久可以进行通信了。

    那么,当客户端发送数据过来的时候,究竟是与哪一个socket对象通信呢?   

    客户端发送过来的数据可以分为2种,一种是连接请求,一种是已经建立好连接后的数据传输。   

    由于TCP/IP协议栈是维护着一个接收和发送缓冲区的。在接收到来自客户端的数据包后,服务器端的TCP/IP协议栈应该会做如下处理:如果收到的是请求连接的数据包,则传给监听着连接请求端口的socetfd套接字,进行accept处理;如果是已经建立过连接后的客户端数据包,则将数据放入接收缓冲区。这样,当服务器端需要读取指定客户端的数据时,则可以利用socketfd_new 套接字通过recv或者read函数到缓冲区里面去取指定的数据(因为socketfd_new代表的socket对象记录了客户端IP和端口,因此可以鉴别)。

    5.int connect(int sockfd,const struct sockaddr *addr, socklen_t addrlen)

    sockfd:socket:客户端socket返回的文件描述符.

    serv_addr:储存了服务器端的连接信息.其中sin_add是服务端的地址

    addrlen:serv_addr的长度

    connect函数是客户端用来同服务端连接的.成功时返回0,sockfd是同服务端通讯的文件描述符失败时返回-1

    原文:https://blog.csdn.net/weililansehudiefei/article/details/78111569

  • 相关阅读:
    Mvc+三层(批量添加、删除、修改)
    js中判断复选款是否选中
    EF的优缺点
    Git tricks: Unstaging files
    Using Git Submodules
    English Learning
    wix xslt for adding node
    The breakpoint will not currently be hit. No symbols have been loaded for this document."
    Use XSLT in wix
    mfc110ud.dll not found
  • 原文地址:https://www.cnblogs.com/aaronRhythm/p/11007999.html
Copyright © 2011-2022 走看看