美文网首页上嵌学习笔记网络编程
系统与网络编程-(网络编程初讲)

系统与网络编程-(网络编程初讲)

作者: I踏雪寻梅 | 来源:发表于2016-12-08 19:36 被阅读42次

    系统与网络编程

    OSI模型

    • 应用层,表示层,会话层,传输层,网络层,数据链路层,物理层
    Paste_Image.png

    socket

    • 在网络编程中经常会接触到套接字,即socket,他是通过标准unix文件描述符和其他程序通信的一个方法
    • 一个完整的socket有一个本地唯一的socket号,由操作系统分配。
    • 直观的描述:
      • socket实际上提供了进程通信的端点,进行通信之前,双方必须先各自创建一个端点,否则无法进行通信。
    • 两设备连接时产生的关联

      {协议,本地地址,本地端口,远程地址,远程端口}

    • 套接字的类型:
      • 流式套接字(SOCK_SREAM),数据报套接字(SOCK_DGRAM),原始套接字。
      • 流式套接字
        • 提供可靠地,面向连接的通讯流(TCP)


          Paste_Image.png
      • 数据报套接字
        • 无序传输且不保证可靠(UDP)


          Paste_Image.png
      • 原始套接字
        link

    socket使用

    • struct sockaddr:用来存储套接字的地址(通用套接字地址)
    struct sockaddr
    {
        unsigned chort sa_family;//address簇,AF_XXX;
        char sa_data[14];/*14byte的协议地址*/
    }
    
    • 一般来说,sa_family都是"AFINET"
    • SA_DATA包含了一些远程电脑的地址,端口,套接字的数目,它里面的数据是融合的。
    • struct sockaddr_in:struct sockaddr_in(in 代表Internet)(网际套接字地址)
    struct sockaddr_in
    {
        short int sin_family;//internet地址族
        unsigned short int sin_port;//端口号
        struct int_addr sin_addr;//internet地址
        unsigned char sin_zero[8];//添0(和struct sokcaddr一样大小)
    }
    
    • struct in_addr
    //因特网地址
    struct in_addr
    {
        unsigned long s_addr;
    };
    
    • 使用sockaddr的时候要把sin_zero全部设成0值。使用bzero或memset

    转换函数

    • htons():将一个短型数据从主机字节顺序转换到网络字节顺序(无符号短型)
    • htonl():将一个短型数据从主机字节顺序转换到网络字节顺序(无符号长型)
    • ntohs():网络字节转为主机字节顺序(无符号短型)
    • ntohl():网络字节转为主机字节顺序(无符号长型)

    IP地址转换

    • inet_addr与inet_ntoa
    struct sockaddr_in ina;
    ina.sin_addr.s_addr=inet_addr("192.168.16.1");//存储ip
    printf("%s",inet_ntoa(ina.sin_addr));//读取出ip地址
    

    inet_ntoa每次调用都会改变函数结果

    char *a1,*a2;
    a1=inet_ntoa(ina1.sin_addr);//"192.168.16.1"
    a2=inet_ntoa(ina2.sin_addr);//"192.168.16.2"
    printf("address 1:%s\n",a1);
    printf("address 1:%s\n",a1);
    
    

    结果会显示:

    address 1:192.168.16.2

    address 2:192.168.16.2

    基本套接字的使用

    • socket(),blind(),connect(),listen(),accept(),等......
    • 格式
      • int socket(int domain, int type, int protocol);
        • 取得套接字描述符,其实就是一个文件描述符
        • 参数描述
          1. domain参数需要被设置成AF_INET
          2. type告诉内核这个socked是什么类型
          3. 参数见man,protocol设置为0。
      • int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
        • 指定一个套接字使用的端口
        • 参数描述
          1. sockfd是由socket()函数返回的套接字描述符;
          2. my_addr是一个指向struct sockaddr的指针,包含名称,端口,IP地址;
          3. addrlen可以设置为sizeof(struct sockaddr)
          #include <string.h>
          

      include <stdio.h>

      include <sys/types.h>

      include <sys/socket.h>

      include <errno.h>

      include <netinet/in.h>

      include <sys/socket.h>

           #include <netinet/in.h>
           #include <arpa/inet.h>
      

      define MYPORT 4000

      //因特网地址
      /struct in_addr
      {
      unsigned long s_addr;
      };
      struct sockaddr_in
      {
      short int sin_family;//internet地址族
      unsigned short int sin_port;//端口号
      struct in_addr sin_addr;//internet地址
      unsigned char sin_zero[8];//添0(和struct sokcaddr一样大小)
      };
      /
      int main()
      {
      int sockfd;
      struct sockaddr_in my_addr;
      sockfd=socket(AF_INET,SOCK_STREAM,0);
      if(sockfd==-1)
      {
      perror("socket");
      return -1;
      }
      my_addr.sin_family=AF_INET;
      my_addr.sin_port=htons(0);
      my_addr.sin_addr.s_addr=htonl(INADDR_ANY);//使用自己的IP
      bzero(&(my_addr.sin_zero),8);
      int ret=-1;
      ret=bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr));
      if(ret==-1)
      {
      perror("errno");
      return -1;
      }
      printf("%s\n",inet_ntoa(my_addr.sin_addr));
      }
      - int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
          - 网络连接部分函数
          - 参数说明:
              1. sockfd:套接字文件描述符,由socket()函数返回形成的
              2. addr:一个存储远程计算机的IP地址和端口信息的结构
              3. addrlen:sizeof(struct sockaddr)
          - 使用connect函数并不需要bind指定端口。
      - int listen(int sockfd, int backlog);
          - listen是等待别人连接进行系统侦听的函数
          - 参数说明:
              1. sockfd:是一个套接字描述符,由socket()系统调用获得
              2. backlog是未经过处理的连接请求队列可容纳的最大数目
                  > **每个请求都要进入一个连入请求队列,等待listen的程序调用accept(),当系统还没用accept的时候,本地能等待的最大数目就是backlog的数值,在调用listen之前要用bind指定端口**
                  
      -  int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
          - accept讲解
              1. 有人从遥远的尝试调用connect()来连接你的机器上的某个端口,(自己的机器是在listen状态)
              2. 他的连接将会被listen加入等待队列等待accept(),等待队列的最大数目由listen的backlog来决定
              3. 调用accept()告诉计算机准备连接
              4. accept返回一个新的套接字描述符,该描述符代表这个连接。
          - 参数含义
              1. sockfd:是正在向listen(的一个套接字描述符)
              2. addr:一般是一个纸箱struct addr_in的结构指针,存储着远方到来计算机的信息(比如计算机的IP地址和端口)
              3. addrlen:是一个本地的整型数值,在他地址传给accept()之前他是一个sizeof(struct sockaddr_in)
      

    客户端与服务器端流式套接字

    • client端程序
      #include<sys/types.h>
      #include<sys/socket.h>
      
      #include<stdio.h>
      #include<string.h>
      #include<netinet/in.h>//struct sockaddr_in
      int main(void)
      {
          int sockfd=-1;
          //创建socket描述符,用于监听接受客户端的连接
          //AF_INET:ipv4
          //SOCK_STREAM:tcp协议
          sockfd=socket(AF_INET,SOCK_STREAM,0);////取得一套接字描述符
          if(sockfd==-1)
          {
              perror("socket");//失败则给出失败信息
              return -1;
          }
          int ret=-1;
          struct sockaddr_in serverAddr;  //服务器的地址
          serverAddr.sin_family=AF_INET;//主机字节顺序
          serverAddr.sin_port=htons(8888);//网络字节
          serverAddr.sin_addr.s_addr=inet_addr("127.0.0.1");//将整型转换成IP
          bzero(&(serverAddr.sin_zero),8);//将剩余空间清零
          ret=connect(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr));//连接服务器
          if(-1==ret)
          {
              perror("connect");
              return -1;
          }
          //rver ip
          while(1)
          {
              
              char caBuf[32]={'\0'};
              scanf("%s",caBuf);
              write(sockfd,caBuf,strlen(caBuf));
              /*
          write(sockfd,"hello nidaye",12);
      
          char caBuf[32]={'\0'};
          read(sockfd,caBuf,sizeof(caBuf));
          printf("%s\n",caBuf);
          */
          }
          return 0;
      }
      

    程序仅能实现服务器端与客户端的连接消息通信,也可以实现在两台电脑之间的通信,一台作为服务器,不能消息群发。

    相关文章

      网友评论

        本文标题:系统与网络编程-(网络编程初讲)

        本文链接:https://www.haomeiwen.com/subject/qbbsmttx.html