• 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
  • 相关阅读:
    升级到virtualbox2.1.4
    gentool 工具 modulerebuild
    解决man乱码问题
    关于HyperV的Linux驱动
    使用tmpfs优化firefox
    使用gmbox下载google歌曲
    升级到xorgserver1.5时出现的问题
    windows下使用where命令
    CSS中一些渐变效果与透明
    asp.net下密码框的一些小问题
  • 原文地址:https://www.cnblogs.com/lxy2019/p/15616555.html
Copyright © 2020-2023  润新知