zoukankan      html  css  js  c++  java
  • Ch13 TCP/IP和网络编程

    Ch13 TCP/IP和网络编程

    13.2 TCP/IP

    TCP/IP数据流路径

    image

    13.3 IP主机和IP地址

    • 主机是支持TCP/IP协议的计算机或设备。

    • IP地址分为两部分,即NetworkID字段和HostID字段。

    13.4 IP协议

    • IP协议用于在IP主机之间发送/接收数据包,IP协议尽最大努力交付数据包。

    13.5 IP数据包格式

    IP数据包由IP头、发送方IP地址和接收方IP地址以及数据组成。每个IP数据包的大小最大为64KB。

    13.12 网络编程

    13.12.2 服务器-客户机计算模型

    大多数网络编程任务都基于服务器-客户机计算模型。在服务器-客户机计算模财中我们首先在服务器主机上运行服务器进程。然后,我们从客户机主机运行客户机在UDP中,服务器等待来自客户机的数据报,处理数据报并生成对客户机的响应。在TCP中,服务器等待客户机连接。客户机首先连接到服务器,在客户机和服务器之间建立一个虚拟电路,建立连接后,服务器和客户机可以交换连续的数据流。


    13.13 套接字编程

    在网络编程中,TCP/IP的用户界面是通过一系列C语言库函数和系统调用来实现的, 这些函数和系统调用统称为套接字API (( Rago 1993; Stevens等2004 )。

    13.13.1 套接字地址

    struct sockaddr_in {
    sa_family_t sin_family; // AF_INET for TCP/IP
    in_port_t sin_port; // port number
    struct in_addr sin_addr; // IP address
    };
    struct in_addr { // internet address
    uint32_t s_addr; // IP address in network byte order
    };
    
    • TCP/IP 网络的 sin_family 始终设置为 AF_INET。
    • sm_port包含按网络字节顺序排列的端口号。
    • sin_addr是按网络字节顺序排列的主机IP地址。

    13.13.2 套接字API

    1. init套接字

      //udp
      int udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
      //tcp
      int tcp_sock = socket(AF_INET, SOCK_STRAM, 0);
      
    2. int bind(int sockfd, struct sockaddr *addr, socklen_t addrlen)

    3. UDP套接字

      ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
      ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
      
    4. TCP套接字

      int listen(int sockfd, int backlog);
      int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
      int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
      
      
    5. send()/read() and recv/write()

      ssize_t send(int sockfd, const void *buf, size_t len, int flags);
      ssize_t write(sockfd, void *buf, size_t, len)
      ssize_t recv(int sockfd, void *buf, size_t len, int flags);
      ssize_t read(sockfd, void *buf, size_t len);
      

    ------------恢复内容开始------------

    # Ch13 TCP/IP和网络编程

    13.2 TCP/IP

    TCP/IP数据流路径

    image

    13.3 IP主机和IP地址

    • 主机是支持TCP/IP协议的计算机或设备。

    • IP地址分为两部分,即NetworkID字段和HostID字段。

    13.4 IP协议

    • IP协议用于在IP主机之间发送/接收数据包,IP协议尽最大努力交付数据包。

    13.5 IP数据包格式

    IP数据包由IP头、发送方IP地址和接收方IP地址以及数据组成。每个IP数据包的大小最大为64KB。

    13.12 网络编程

    13.12.2 服务器-客户机计算模型

    大多数网络编程任务都基于服务器-客户机计算模型。在服务器-客户机计算模财中我们首先在服务器主机上运行服务器进程。然后,我们从客户机主机运行客户机在UDP中,服务器等待来自客户机的数据报,处理数据报并生成对客户机的响应。在TCP中,服务器等待客户机连接。客户机首先连接到服务器,在客户机和服务器之间建立一个虚拟电路,建立连接后,服务器和客户机可以交换连续的数据流。


    13.13 套接字编程

    在网络编程中,TCP/IP的用户界面是通过一系列C语言库函数和系统调用来实现的, 这些函数和系统调用统称为套接字API (( Rago 1993; Stevens等2004 )。

    13.13.1 套接字地址

    struct sockaddr_in {
    sa_family_t sin_family; // AF_INET for TCP/IP
    in_port_t sin_port; // port number
    struct in_addr sin_addr; // IP address
    };
    struct in_addr { // internet address
    uint32_t s_addr; // IP address in network byte order
    };
    
    • TCP/IP 网络的 sin_family 始终设置为 AF_INET。
    • sm_port包含按网络字节顺序排列的端口号。
    • sin_addr是按网络字节顺序排列的主机IP地址。

    13.13.2 套接字API

    1. init套接字

      //udp
      int udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
      //tcp
      int tcp_sock = socket(AF_INET, SOCK_STRAM, 0);
      
    2. int bind(int sockfd, struct sockaddr *addr, socklen_t addrlen)

    3. UDP套接字

      ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
      ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
      
    4. TCP套接字

      int listen(int sockfd, int backlog);
      int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
      int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
      
      
    5. send()/read() and recv/write()

      ssize_t send(int sockfd, const void *buf, size_t len, int flags);
      ssize_t write(sockfd, void *buf, size_t, len)
      ssize_t recv(int sockfd, void *buf, size_t len, int flags);
      ssize_t read(sockfd, void *buf, size_t len);
      

    代码实践

    参考书上的代码编写了UDP的server端和client端。

    UDP

    • server端代码
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <netinet/ip.h>
    #include <arpa/inet.h>
    #define BUFLEN 256
    #define PORT 1234
    
    char line[BUFLEN];
    struct sockaddr_in me, client;
    int sock, rlen, clen = sizeof(client);
    
    int main(){
    	printf("1. create a UDP socket\n");
    	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    	
    	printf("2. file me with server address and port number\n");
    	memset((char *)&me, 0, sizeof(me));	
    	me.sin_family = AF_INET;
    	me.sin_port = htons(PORT);
    	me.sin_addr.s_addr = htonl(INADDR_ANY);
    
    	printf("3. bind socket to server IP and port\n");
    	bind(sock, (struct sockaddr*)&me, sizeof(me));
    
    	printf("4. wait for datagram\n");
    	while(1){
    	memset(line, 0, BUFLEN);
    	printf("UDP server: waiting for datagram\n");
    	
    	rlen = recvfrom(sock, line, BUFLEN, 0, (struct sockaddr *)&client, &clen);
    	printf("recevied a datagram from [host:port] = [%s:%d]\n",
    		inet_ntoa(client.sin_addr), ntohs(client.sin_port));
    	printf("rlen=%d: line=%s\n", rlen, line);
    	printf("send reply\n");
    	sendto(sock, line, rlen, 0, (struct sockaddr*)&client, clen);
    }
    	return 0;
    }
    
    • client端代码
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <netinet/ip.h>
    
    
    #define SERVER_HOST "127.0.0.1"
    #define SERVER_PORT 1234
    #define BUFLEN 256
    
    char line[BUFLEN];
    struct sockaddr_in server;
    int sock, rlen, slen=sizeof(server);
    
    int main(){
    	printf("1. create a UDP socket\n");
    	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    	
    	printf("2. fill in server address and port number\n");
    	memset((char *) &server, 0, sizeof(server));
    	server.sin_family = AF_INET;
    	server.sin_port = htons(SERVER_PORT);
    	inet_aton(SERVER_HOST, &server.sin_addr);
    
    	while(1){
    	printf("Enter a line :" );
    	fgets(line, BUFLEN, stdin);
    	line[strlen(line)-1] = 0;
    	printf("send line to server\n");
    	sendto(sock, line, strlen(line), 0, (struct sockaddr *)&server, slen);
    	memset(line, 0, BUFLEN);
    	printf("try to receive a line from server\n");
    	rlen = recvfrom(sock, line, BUFLEN, 0, (struct sockaddr *)&server, &slen);
    	printf("rlen=%d : line=%s\n", rlen, line);
    }
    	return 0;
    }
    
    • 运行结果
      image
      image

    TCP

    • sever端代码
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    
    #define MAX 256
    #define SERVER_HOST "localhost"
    #define SERVER_IP "127.0.0.1"
    #define SERVER_PORT 1234
    
    struct sockaddr_in server_addr, client_addr;
    int mysock, csock; // socket descriptors
    int r, len, n;     // help variables
    
    int server_init()
    {
        printf("================== server init ======================\n");
    
        // create a TCP socket by socket() syscall
        printf("1 : create a TCP STREAM socket\n");
        mysock = socket(AF_INET, SOCK_STREAM, 0);
    
        if (mysock < 0)
        {
            printf("socket call failed\n");
            exit(1);
        }
        printf("2 : fill server_addr with host IP and PORT# info\n");
        // initialize the server_addr structure
        server_addr.sin_family = AF_INET;                // for TCP/IP
        server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // This HOST IP
        server_addr.sin_port = htons(SERVER_PORT);       // port number 1234
        printf("3 : bind socket to server address\n");
        r = bind(mysock, (struct sockaddr *)&server_addr, sizeof(server_addr));
        if (r < 0)
        {
            printf("bind failed\n");
            exit(3);
        }
        printf(" hostname = %s port = %d\n", SERVER_HOST, SERVER_PORT);
        printf("4 : server is listening ....\n");
        listen(mysock, 5); // queue length = 5
        printf("=================== init done =======================\n");
    }
    int main()
    {
        char line[MAX];
        server_init();
        while (1)
        { // Try to accept a client request
            printf("server: accepting new connection ....\n");
            // Try to accept a client connection as descriptor newsock
            len = sizeof(client_addr);
            csock = accept(mysock, (struct sockaddr *)&client_addr, &len);
            if (csock < 0)
            {
                printf("server: accept error\n");
                exit(1);
            }
            printf("server: accepted a client connection from\n");
            printf("---------------------------------------------–\n");
            printf("Clinet: IP=%s port=%d\n",
                   inet_ntoa(client_addr.sin_addr),
                   ntohs(client_addr.sin_port));
            printf("---------------------------------------------–\n");
            // Processing loop: client_sock <== data ==> client
            while (1)
            {
                n = read(csock, line, MAX);
                if (n == 0)
                {
                    printf("server: client died, server loops\n");
                    close(csock);
                    break;
                }
                // show the line string
                printf("server: read n=%d bytes; line=%s\n", n, line);
                // echo line to client
                n = write(csock, line, MAX);
                printf("server: wrote n=%d bytes; ECHO=%s\n", n, line);
                printf("server: ready for next request\n");
            }
        }
    }
    
    
    • client端代码
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #define MAX 256
    #define SERVER_HOST "localhost"
    #define SERVER_PORT 1234
    struct sockaddr_in server_addr;
    int sock, r;
    int client_init()
    {
        printf("======= clinet init ==========\n");
        printf("1 : create a TCP socket\n");
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0)
        {
            printf("socket call failed\n");
            exit(1);
        }
        printf("2 : fill server_addr with server’s IP and PORT#\n");
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // localhost
        server_addr.sin_port = htons(SERVER_PORT);       // server port number
        printf("3 : connecting to server ....\n");
        r = connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
        if (r < 0)
        {
            printf("connect failed\n");
            exit(3);
        }
        printf("4 : connected OK to\n");
        printf("-------------------------------------------------------\n");
        printf("Server hostname=%s PORT=%d\n", SERVER_HOST, SERVER_PORT);
        printf("-------------------------------------------------------\n");
        printf("========= init done ==========\n");
    }
    int main()
    {
        int n;
        char line[MAX], ans[MAX];
        client_init();
        printf("******** processing loop *********\n");
        while (1)
        {
            printf("input a line : ");
            bzero(line, MAX);           // zero out line[ ]
            fgets(line, MAX, stdin);    // get a line from stdin
            line[strlen(line) - 1] = 0; // kill \n at end
            if (line[0] == 0)           // exit if NULL line
                exit(0);
            // Send line to server
            n = write(sock, line, MAX);
            printf("client: wrote n=%d bytes; line=%s\n", n, line);
            // Read a line from sock and show it
            n = read(sock, ans, MAX);
            printf("client: read n=%d bytes; echo=%s\n", n, ans);
        }
    }
    
    • 运行截图
      image
      image
  • 相关阅读:
    【React Native】某个页面禁用物理返回键
    【React Native】DeviceEventEmitter监听通知及带参数传值
    转载【React Native代码】手写验证码倒计时组件
    【React Native】 中设置 APP 名称、应用图标、为安卓添加启动图
    【React Native错误集】* What went wrong: Execution failed for task ':app:installDebug'.
    【React Native错误集】Import fails with "Failed to execute 'ImportScripts' on 'WorkerGlobalScope'"
    【React Native错误集】Android error “Could not get BatchedBridge, make sure your bundle is packaged properly” on start of app
    「React Native笔记」在React的 setState 中操作数组和对象的多种方法(合集)
    【React Native】Error: Attribute application@allowBackup value=(false) from AndroidManifest.xml
    坚果云如何使用二次验证码/谷歌身份验证器/两步验证/虚拟MFA?
  • 原文地址:https://www.cnblogs.com/lxy2019/p/15616555.html
Copyright © 2011-2022 走看看