学习笔记11

第一部分:教材知识总结

学习目标

通过本章的学习,了解TCP/IP协议及其应用,包括...

  • TCP/IP协议栈
  • IP地址、主机名、DNS、IP数据包和路由器
  • TCP/IP协议簇中的UDP和TCP协议、端口号和数据流
  • 套接字及通过简单编程加深理解
  • Web和CGI编程,HTTPD服务器,HTTP编程模型,Web服务器的配置和运行

网络编程的本质

网络编程是使用IP地址、域名和端口连接到另一台计算机上对应的程序,按照规定的协议交换数据。它主要涉及两个设备之间的数据交换,在计算机网络中通常指计算机之间的数据传递。

TCP/IP协议

TCP/IP是能够在多个不同网络间实现信息传输的协议簇,包括FTP、SMTP、TCP、UDP、IP等协议。TCP代表传输控制协议,IP代表互联网协议。IPv4使用32位地址,IPv6使用128位地址。

IP主机和IP地址

每个主机都有一个本地主机名localhost,默认 IP地址为 127.0.0.1。

本地主机的链路层是一个回送虚拟设备,它将每个数据包路由回同一个localhost。这个特性可以让我们在同一台计算机上运行TCP/IP 应用程序,而不需要实际连接到互联网。

IP地址分为两部分,即 NetworkID 字段和HostID字段。根据划分,IP 地址分为A~E类。

IP协议

IP协议用于在 IP主机之间发送/接收数据包。IP尽最大努力运行。IP 主机只向接收主机发送数据包,但它不能保证数据包会被发送到它们的目的地,也不能保证按顺序发送。这意味着IP 并非可靠的协议。

路由器

是接收和转发数据包的特殊IP主机。一个IP数据包可能会经过许多路由器,或者跳跃到达某个目的地。每个IP包在IP报头中都有一个8位生存时间(TTL)计数,其最大值为255。

UDP

UDP(用户数据报协议)(RFC768 1980;Comer 1988)在IP上运行,用于发送/接收数据报。与IP类似,UDP不能保证可靠性,但是快速高效。

TCP

TCP(传输控制协议)是一种面向连接的协议,用于发送/接收数据流。TCP也可在IP 上运行,但它保证了可靠的数据传输。

端口编号

端口号是分配给应用程序的唯一无符号短整数。要想使用UDP或TCP,应用程序(进程)必须先选择或获取一个端口号。前1024个端口号已被预留。其他端口号可供一般使用。应用程序可以选择一个可用端口号,也可以让操作系统内核分配端口号。

端口号的范围从0到65535。

使用 netstat -nao 可以查看系统中端口的活动情况。

编程练习1:使用C语言实现简单UDP传输

客户端代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#define MAXBUF 256
int main(int argc, char const *argv[])
{
    int s = 0;
    int n = 0;
    int reuse = 1;
    int port = 1987;
    struct sockaddr_in srv;
    char buf[MAXBUF] = {0};
    /*解析参数*/
    if (argc != 2)
    {
        printf("Usage:%s ServerIP\n", argv[0]);
        return -1;
    }
 
    bzero(&srv, sizeof(srv));
    srv.sin_family = PF_INET;
    srv.sin_addr.s_addr = inet_addr(argv[1]);
    srv.sin_port = htons(port);
    /*创建 UDP 套节字*/
    s = socket(AF_INET, SOCK_DGRAM, 0);
    if(s<0){
        perror("socket");
        return -1;
    }
 
    while(1){
        memset(buf, 0, MAXBUF);
        /*读取用户输入到buf中*/
        fgets(buf, MAXBUF, stdin);
 
        /*通过套节字 s 向服务器发送数据*/
        if ((n = sendto(s, buf, strlen(buf), 0, (struct sockaddr *) &srv, sizeof(struct sockaddr))) < 0)
        {
            perror("sendto");
            return -1;
        }else{
            printf("send to %s(port=%d) len %d:%s\n", argv[1], port, n, buf);
        }
    }
}
服务端代码
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <netinet/ip.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.fill 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);//use localhost        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("received 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);        }}

编程练习2:使用C语言实现简单TCP传输

服务器代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define MAX 256
#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(" port = %d\n", 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 connection as descriptor newsock
        printf("server: accepting new connection ....\n");
        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("Client: 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");
        }
    }
}

客户端代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define MAX 256
#define SERVER_PORT 1234
#define SERVER_HOST "127.0.0.1" // Use the server's IP address

struct sockaddr_in server_addr;
int sock, r;

int client_init()
{
    printf("======= client 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 = inet_addr(SERVER_HOST); // Server's IP
    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 IP=%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 the 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);
    }
}

苏格拉底挑战

posted @ 2023-11-26 21:58  卢泽  阅读(1)  评论(0编辑  收藏  举报