• MFC网络编程


    最近这段时间,一直都在学习套接字编程,下面就写写自己学习的一些相关知识,也算是学习笔记吧(这篇文章主要参考孙鑫老师的教学视频和相关文档)。

    首先是关于WinSocket网络编程方面的:

    一、套接字的类型:

       主要有三类:1、流式套接字(SOCK_STREAM),主要提供面向连接、可靠地数据传输服务,数据能够无差错的无重复的发送,并且能够按顺序的进行接收,主要基于TCP协议实现的

                         2、数据报式套接字(SOCK_DGRAM),主要提供无连接的服务,数据包能够独立的进行发送,不提供无错保证,数据可能会丢失或者重复,并且接收的顺序比较混乱,这种类型主要基于UDP协议实现的,所以这种类型的即时性比较高。(聊天通讯软件一般都是采用这种形式实现的)

                         3、原始套接字(SOCK_RAW),这种套接字一定要在root下使用,可以接受到本机网卡上的数据帧或者数据包,对于监听网络的流量和分析是很有作用的。

     

    二、基于TCP(面向连接)socket编程的程序编写流程:

    1、服务器端程序流程

        a、创建套接字(socket)。

        b、将套接字绑定到一个本地地址和端口上(bind)。

        c、将套接字设为监听模式,准备接受客户请求(listen)。

        d、等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)

        e、用返回的套接字和客户端进行通信(send/recv)。

        f、返回,等待另一个客户请求。

        g、关闭套接字

     

    2、客户端程序编写流程

        a、创建套接字(socket)。

        b、向服务器发出连接请求(connect)。

        c、和服务器端进行通信(send/recv)。

        d、关闭套接字。

     

     服务器端程序编写流程:

     1、创建套接字(socket).

    SOCKET socket (
        int af, //指定的地址族,对于TCP/IP协议的套接字,他只能是AF_INET(也可以写成PF_INET)
        int type, //指定socket类型,对于1.1版本的socket,它支持两种类型的套接字,SOCK_STREAM指定产生流式套接字,SOCK_DGRAM指定产生数据报式套接字
        int protocol //是与特定的地址族相关的协议,如果指定为0,那么系统会根据地址格式和套接字类别,自动选择一个合适的协议(推荐这么使用)
    ); 
    

     2、将套接字绑定到一个本地地址和端口上(bind).

    int bind(
        SOCKET s,  //要绑定的套接字                        
        const struct sockaddr FAR *name,   //指定了该套接字的本地地址信息,这是一个指向sockaddr结构的指针变量,由于该地址结构是为所有的地址家族准备的,这个结构通常会随使用的网络协议不同而不同  
        int namelen   //指定该地址结构的长度                    
    );

    a、sockaddr结构的定义如下(可以用sockaddr_in结构替换sockaddr,以方便我们填写地址信息):

    struct sockaddr {
      	u_short    sa_family;
      	char       sa_data[14];
    };  
    struct sockaddr_in{
     	short sin_family;
    	unsigned short sin_port;
     	IN_ADDR sin_addr;
     	char sin_zero[8];
    };

    另外,sockaddr_in结构中的sin_addr成员的类型是in_addr,其结构定义如下:

    struct in_addr {
      union {
              struct { u_char s_b1,s_b2,s_b3,s_b4; }   S_un_b;
              struct { u_short s_w1,s_w2; }            S_un_w;
              u_long                                   S_addr;
      } S_un;
    };
    

    in_addr结构实际上是一个联合,通常利用这个结构将一个点分十进制格式的IP地址转换成u_long类型,并将结果赋给成员S_addr。

    可以把IP地址指定为INADDR_ANY,允许套接字向任何分配给本地机器的IP地址发送或者接受数据。

    b、inet_addr函数和inet_ntoa函数

    多数情况下,每个机器只有一个IP地址,但是有的机器可能会有多个网卡,每个网卡都可以有自己的IP地址,用INADDR_ANY可以简化程序的编写,将地址指定为INADDR_ANY,将允许一个独立应用接受发自多个接口的回应。如果我们只想让套接字使用多个IP中的一个地址,就必须指定实际的地址,要做到这一点,可以用inet_addr函数来实现,该函数的原型声明如下:

    unsigned long inet_addr (const char *cp ); 

    inet_addr函数需要一个字符串作为其参数,该字符串指定了以点分十进制格式表示的IP地址。而且inet_addr函数会返回一个适合分配给S_addr的u_long类型的数值。

    inet_ntoa函数会完成相反地转换,他接受一个in_addr结构体类型的参数并返回一个以点分十进制格式表示的IP地址字符串。该函数的原型声明如下:

    char * inet_ntoa (struct in_addr in ); 

    3、将套接字设为监听模式,准备接受客户请求(listen)

    listen函数的作用是将指定的套接字设置为监听模式。其声明原型如下:

    int listen (
    SOCKET s,  //套接字描述符 
    int backlog   等待连接队列的最大长度 
    ); 

    对于第二个参数backlog,如果设置为SOMAXCONN,那么下层的服务提供者将负责将这个套接字设置为最大的合理值。要注意的是,设置这个值是为了设置等待连接队列的最大长度,而不是在一个端口上同时可以进行连接的数目。例如,如果将backlog参数设置为2,当有3个请求同时到来时,前两个连接请求就会被放到等待请求连接队列中,然后由应用程序依次为这些请求服务,而第3个连接请求就被拒绝了。

    4、等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。

    SOCKET accept(
    SOCKET s, //套接字描述符,该套接字已经通过listen函数将其设置为监听状态
    struct sockaddr *addr,  // 指向一个缓冲区的指针,该缓冲区用来接受连接实体的地址,也就是当客户端向服务器发起连接,服务器接受这个连接时,保存发起连接的这个客户端的IP地址信息和端口信息
    int *addrlen   //也是一个返回值,指向一个整型的指针,返回包含地址信息的长度
    ); 

    未完待续。。。

     

     

     

  • 相关阅读:
    火山喷发 计蒜客16862 NOIP模拟赛 概率DP
    洛谷 1429 平面最近点对(加强版) 快排 非点分治或kdtree
    鬼脚图 计蒜客17353 NOIP模拟 归并排序逆序对
    小X的佛光 NOIP模拟赛 倍增LCA 树结构
    小X的质数 NOIP模拟赛 魔改线性筛素数
    Win7Office2010Flash控件无法使用"此演示文稿中一些控件无法激活,可能这些控件未在此计算机中注册"
    【NOILinux】VmWare15使用技巧
    【超链接】导航网站
    C++统计博客园写过的代码行数
    合并多个txt文件到一个
  • 原文地址:https://www.cnblogs.com/jinsedemaitian/p/5589208.html
Copyright © 2020-2023  润新知