zoukankan      html  css  js  c++  java
  • 嵌入式Linux网络编程

    参考书籍:《从实践中学嵌入式linux应用程序开发》(华清远见嵌入式学院)

    代码下载:http://download.csdn.net/detail/klcf0220/5354885

    资料下载:http://www.kuaipan.cn/file/id_43409466388906157.htmhttp://download.csdn.net/detail/klcf0220/7058371)  、  http://www.kuaipan.cn/file/id_43409466388906143.htm

    参考链接:http://www.cnblogs.com/Robotke1/archive/2013/05/07/3064575.html

    TCP/IP协议

    参考链接: http://www.cnblogs.com/dann/archive/2013/02/14/2909869.html

    OSI层次模型:

    OSI层次模型中各层的功能:
       (1) 物理层(PH),确定物理设备接口,提供点-点的比特流传输的物理链路;
       (2) 数据链路层(DL),利用差错处理技术,提供高可靠传输的数据链路;
       (3) 网络层(N),利用路由技术,实现用户数据的端-端传输;
       (4) 运输层(T),屏蔽子网差异,用户要求和网络服务之间的差异;
       (5) 会话层(S),提供控制会话和数据传输的手段 ;
       (6) 表示层(P),解决异种系统之间的信息表示问题,屏蔽不同系统在数据表示方面的差异;
       (7) 应用层(A),利用下层的服务,满足具体的应用要求。

    TCP/IP协议各层的解析:

    (1)网络接口层

      TCP/IP协议模型的基层,负责数据帧的发送和接收。对应OSI模型中的物理层和数据链路层,是TCP/IP的最底层,不过通常在描述TCP/IP模型时还是会划分具体为物理层(PHY)和数据链路层(MAC)。主要负责将二进制流转换为数据帧,并进行数据帧的发送和接收。数据帧是网络传输的基本单元。

    (2)网络层

      通过互联协议将数据包封装成互联网数据包,并运行必要的路由算法。这里有4种互联协议。

      (a)网际协议IP:负责在主机和网络之间的路径寻址和数据包路由。

      (b)地址解析协议ARP:获得同一物理网络中的主机硬件地址。

      (c)网际控制消息协议ICMP:发送消息,并报告有关数据包的传送错误。

      (d)互联组管理协议IGMP:用来实现本地多路广播路由器报告。

    (3)传输层

      传输协议负责提供应用层程序之间的通信服务。传输协议的选择根据数据传输方式而定。主要有以下2种传输协议:

      (a)传输控制协议TCP:为应用程序提供可靠的通信连接,适用于要求得到响应的应用程序。

      (b)用户数据包协议UDP:提供无连接通信,且不对传输包进行可靠性确认。

    (4)应用层

      应用程序通过这一层访问网络,主要包括常见的FTP、HTTP、DNS和TELNET协议。

    套接字

    Socket有三种类型:
    1)流式套接字(SOCK_STREAM)   基于TCP协议
    2)数据报套接字(SOCK_DGRAM)    基于UDP协议
    3)原始套接字(SOCK_RAW)       基于底层协议如IP或ICMP协议,主要用于新的网络协议的开发。

    在socket程序设计中,struct sockaddr 和struct  sockaddr_in用于记录网络地址,

    struct scokaddr
    {
        unsigned short sa_family;//地址族
        char sa_data[14];//14字节的协议地址,包含该socket的IP地址和端口号
    };
    struct scokaddr_in
    {
        short int sin_family;//地址族
        unsigned short int sin_port;//端口号
        struct in_addr sin_addr;//IP地址
        unsigned char sin_zero[8];//填充0以保持与struct sockaddr同样大小
    };

    这两个数据类型是等效的,可以相互转化,通常sockaddr_in 数据类型使用更为方便。

    sa_family 字段可选的常见值:(需要#include<netinet/in.h>头文件)
    AF_INET:IPv4协议
    AF_INET6:IPv6协议
    AF_LOCAL:UNIX域协议
    AF_LINK:链路地址协议
    AF_KEY:秘钥套接字

    数据存储优先顺序:
    字节序的转因为计算机存储有两种字节优先排序:高位字节优先(即大端模式)和低位地址优先(即小端模式),Internet上数据以高位字节优先顺序在网络上传输。所以有些情况下,需要对这两字节存储优先顺序进行相互转化。这里用到4个函数:htons() ,htonl() ,ntohs() ,ntohl();  
    其中h代表host,n代表network,s代表short,l代表long。通常16位的IP端口号用 s 代表,而IP地址用 l 来表示。

    地址格式转换:
    用户表达地址时通常采用点分十进制表示的数值字符串,而在通常使用的socket编程中所用的则是二进制值,这就需要将两个数值进行转换。
    在IPv4中用到的函数有inet_aton(),inet_addr(),inet_ntoa();
    而IPv4和IPv6兼容的函数有inet_pton()和inet_ntop()。

    套接字编程

    socket()                  //创建一个socket
    bind()                      //该函数用于将sockaddr结构的地址信息与套接字进行绑定。主要用于TCP的连接,而在UDP的连接中则没有必要。
    connect()               //该函数用于服务器建立连接
    listen()                    //创建一个等待队列,在其中存放未处理的客户端连接请求。
    accept()                 //用于等待并接收来自客户端的socket连接请求
    send() ,sendto      //发送数据
    recv() ,recvfrom   //接收数据

    Socket网络编程流程图http://blog.csdn.net/zhangyaowen123123/article/details/6738562

    编程实例:

    /*server.c*/
    #include<stdio.h>
    #include<stdlib.h>
    #include<sys/types.h>
    #include<sys/socket.h>
    #include<errno.h>
    #include<string.h>
    #include<unistd.h>
    #include<netinet/in.h>
    #define PORT 4321
    #define BUFFER_SIZE 1024
    #define MAX_QUE_CONN_NM 5
    int main()
    {
        struct sockaddr_in server_sockaddr,client_sockaddr;
        int sin_size,recvbytes;
        int sockfd,client_fd;
        char buf[BUFFER_SIZE];
        
        //建立socket链接
        if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
        {
            perror("socket");
            exit(1);
        }
        printf("socket is = %d\n",sockfd);
    
        //设置sockaddr_in结构体中相关参数
        server_sockaddr.sin_family = AF_INET;
        server_sockaddr.sin_port = htons(PORT);
        server_sockaddr.sin_addr.s_addr = INADDR_ANY;
        bzero(&(server_sockaddr.sin_zero),8);
        
        int i =1;//允许重复使用本地地址与套接字进行绑定
        setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i));
        
        //绑定套接字
        if(bind(sockfd,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr)) == -1)
        {
            perror("bind");
            exit(1);
        }
        printf("bind success\n");
    
        //listen()
        if(listen(sockfd,MAX_QUE_CONN_NM) == -1)
        {
            perror("listen");
            exit(1);
        }
        printf("listen ......\n");
    
        //accept()
        sin_size = sizeof(client_sockaddr);
        if((client_fd = accept(sockfd,(struct sockaddr *)&client_sockaddr,&sin_size)) == -1)
        {
            perror("accept");
            exit(1);
        }
        
        //recv()
        memset(buf,0,sizeof(buf));
        if((recvbytes = recv(client_fd,buf,BUFFER_SIZE,0)) == -1)
        {
            perror("recv");
            exit(1);
        }
        printf("received a message:%s\n",buf);
        close(sockfd);
        exit(0);
    }
    
    /*client.c*/
    #include<stdio.h>
    #include<stdlib.h>
    #include<sys/types.h>
    #include<sys/socket.h>
    #include<errno.h>
    #include<string.h>
    #include<unistd.h>
    #include<netinet/in.h>
    #include<netdb.h>//一定要加上这个头文件,不然会报“提领指向不完全类型的指针”的错误
    #define PORT 4321
    #define BUFFER_SIZE 1024
    int main(int argc,char *argv[])
    {
        struct sockaddr_in serv_addr;
        int sendbytes,sockfd;
        struct hostent *host;
        char buf[BUFFER_SIZE];
        
        if(argc < 3)
        {
            fprintf(stderr,"USAGE: ./client Hostname(or ip address) Text\n");
            exit(1);
        }
        
        //地址解析函数
        if((host = gethostbyname(argv[1])) == NULL)
        {
            perror("gethostbyname");
            exit(1);
        }
        
        memset(buf,0,sizeof(buf));
        sprintf(buf,"%s",argv[2]);
        //建立socket
        if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1)
        {
            perror("socket");
            exit(1);
        }
    
        //设置sockaddr_in结构体中相关参数
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(PORT);
        serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
        bzero(&(serv_addr.sin_zero),8);
        
        //connect()
        if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr)) == -1)
        {
            perror("connect\n");
            exit(1);
        }
        
        //send()
        if((sendbytes = send(sockfd,buf,strlen(buf),0)) == -1)
        {
            perror("send");
            exit(1);
        }
        close(sockfd);
        exit(0);
    }
    作者:快乐出发0220 ;Android群:151319601 ; Linux群:96394158 ;转载请注明出处 http://klcf0220.cnblogs.com/ !!!
  • 相关阅读:
    hdu 4710 Balls Rearrangement()
    hdu 4707 Pet(DFS水过)
    hdu 4706 Children's Day(模拟)
    hdu 4712 Hamming Distance(随机函数暴力)
    csu 1305 Substring (后缀数组)
    csu 1306 Manor(优先队列)
    csu 1312 榜单(模拟题)
    csu 1303 Decimal (数论题)
    网络爬虫
    Python处理微信利器——itchat
  • 原文地址:https://www.cnblogs.com/klcf0220/p/3066977.html
Copyright © 2011-2022 走看看