Socket通信实战代码分解


代码思路:

  1.Server端:

    1.创建WSADATA变量

    2.创建SOCKET套接字

      发送消息

    3.

1、WSADATA:一种数据结构,这种数据结构用于存放WSAStartup()函数调用后返回的Windows Sockets数据;

1.1、SOCKAET:创建套接字,相当于一个电话;

2、struct sockaddr_in 这个结构体用于处理 网络通信的地址(目标地址/IP地址 和 端口)

  :sockaddr_in  在头文件 #include 或 #include 中,该结构体把目标地址信息和端口信息存在两个变量中;

      struct sockaddr_in{

        sa_family_t sin_family;     //地址族

        uint16_t sin_port;      //端口信息;16位TCP端口号

        struct sin_addr;       //目标地址信息;32位IP地址;

        char sin_zero[8];        //不使用;

      struct sin_addr{

        In_addr_t s_addr;      //32位IPV4地址;

代码参数解释:

  INADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。


 网络字节序是什么?

   //网络字节顺序 是TCP/IP中规定好的一种数据表示格式,它与具体的 CPU 类型、 操作系统 等无关,从而可以保证数据在不同主机之间传输时能够被正确解释;

   //网络字节序是确定的;


//地址族是什么?

  •   通讯的基石是套接口,一个套接口是通讯的一端;
  •   一个套接口可以理解位一个电话,有号码(地址)和数据完成通信,数据的接收依靠协议完成;
  •   套接口在需要的时候创建,创建的时候需要指定域(domain),即所用的地址族(AF_INET 本地地址族、AF_INET6 网络地址族、AF_IRDA红外地址族;
  •   在windows中 AF_INET 与 PF_INET 完全一样;
  •    绑定所用的地址族sockaddr;

2、struct sockaddr 和 struct sockaddr_in 这两个结构体用于处理 网络通信的地址(目标地址/IP地址 和 端口)

  区别:sockaddr   在头文件 #include 中  缺陷:把目标地址和端口混合了;如下:

    struct sockaddr{

        sa_family sin_family;    //地址族;

        char sa_data[14];      //14字节,包含套接字中的地址信息和端口信息

     :sockaddr_in  在头文件 #include 或 #include 中,该结构体把目标地址信息和端口信息存在两个变量中;

      struct sockaddr_in{

        sa_family_t sin_family;    //地址族

        uint16_t sin_port;      //端口信息;16位TCP端口号

        struct sin_addr;       //目标地址信息;32位IP地址;

        char sin_zero[8];        //不使用;

      struct sin_addr{

        In_addr_t s_addr;      //32位IPV4地址;


 3、send()函数

  函数原型:send(int sockfd, const void *buf, size_t len, int flags);

  函数功能:向对方发送数据,

  参数介绍:

    第一个参数:指定发送端套接字描述符;

    第二个参数:指明一个存放应用程序要发送数据的缓冲区;

    第三个参数:指明实际要发送的数据的字节数;

    第四个参数:一般置0。

  返回值:

    发送成功:返回发送数据的字节数;

    发送失败:返回-1 或 SOCKET_ERROR

 4、recv函数

  函数原型:int recv( SOCKET s, char FAR *buf, int len, int flags);

   函数功能:接收数据,调用recv()函数会从接收socket的接收缓冲区读取数据存放到用户层的buffer里面;

  参数介绍:第一个参数:指定接收端套接字描述符;

          第二个参数:指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;

       第三个参数:指明buf的长度;

       第四个参数:一般置0;

  返回值:情况1:成功执行时,返回接收到的字节数。

      情况2:另一端已关闭则返回0。

      情况3:失败返回-1,

      情况4:SOCKER_ERROR等,错误原因有 内存不足等、

4.1 接收缓冲区和发送缓冲区与send() 和 recv()的关系;

  原载:(4条消息) socket的send(),recv()以及缓冲区之间的关系_zj134_的博客-CSDN博客_recv缓冲区

  接收缓冲区:对端发送来的数据会一直存放在socket的内核接收缓冲区中,进程调用recv()函数的时候,会从接收socket的接收缓冲区读取数据存放到用户层的buffer里面,然后返回

  发送缓冲区:进程调用send()函数的时候,会把用户层buffer里面的数据拷贝的socket的发送缓冲区,之后函数就返回了。

    ( 也就是说send() 返回的时候,数据不一定发送了,只是完成了copy动作。)


5.connect()

  函数原型int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

  函数功能:用于建立与指定socket的连接;

  参数介绍:第一个参数 :socket文件描述符;

          第二个参数:指定服务器端地址信息,含IP地址和端口号;

       第三个参数:sizeof(addr) 大小;

  返回值:成功返回0,失败返回-1;