2023-2024-1 20211327 信息安全系统设计与实现 学习笔记11

学习笔记11

  • 网络编程与TCP/IP协议
  • 网络与套接字编程
  • 服务器——客户机程序
  • Web和CGI编程
  • 实践过程

网络基础与TCP/IP协议

网络基础

  • 套接字(Socket): 套接字是网络编程的基础。它是一种通信机制,允许程序通过网络进行数据传输。套接字提供了一种标准的接口,使得应用程序可以通过网络发送和接收数据。

  • IP地址与端口号: 在网络中,每台计算机都有一个唯一的IP地址,用于标识其在网络中的位置。端口号用于标识一个应用程序,使得数据能够正确传递到相应的应用。

  • 协议: 在网络编程中,常用的协议包括TCP(传输控制协议)和UDP(用户数据报协议)。TCP提供可靠的、面向连接的通信,而UDP提供不可靠的、面向无连接的通信。

  • 服务器与客户端: 在网络编程中,通常会涉及到服务器和客户端。服务器是提供服务的一方,而客户端是请求服务的一方。服务器在一个特定的端口上监听客户端的连接请求。

  • HTTP与HTTPS: 超文本传输协议(HTTP)是用于在Web上进行数据通信的协议。HTTPS是HTTP的安全版本,通过使用SSL/TLS协议进行加密通信,提高了数据的安全性。

  • 网络库与框架: 许多编程语言提供了网络编程的库和框架,简化了网络应用程序的开发。例如,Python中的socket库,Java中的java.net包,以及Web框架如FlaskDjango都包含了网络编程的支持。

  • 异步编程: 随着网络应用的复杂性增加,异步编程变得越来越重要。异步编程允许程序在等待网络数据的同时执行其他任务,提高了程序的效率和响应性。例如,Python中的asyncio库提供了异步编程的支持。

TCP/IP协议

TCP/IP协议是一组用于互联网通信的协议,它是网络世界中最基础、最重要的协议之一。TCP/IP指的是传输控制协议(TCP)和因特网协议(IP),它们共同构成了一个层次化的协议栈。

1. TCP(传输控制协议):

  • 特点: 面向连接、可靠、基于字节流。
  • 功能: 提供可靠的数据传输服务,确保数据的有序性和完整性。通过流控制、拥塞控制等机*制来维护网络通信的稳定性。
  • 连接: 在通信之前,需要通过三次握手建立连接,以及四次握手来终止连接。
  • 流量控制: 通过滑动窗口机制控制发送方的发送速率,防止接收方来不及处理过多的数据。
  • 拥塞控制: 避免在网络拥塞时导致性能下降,通过动态调整传输速率来维护网络的健康状态。

2. IP(因特网协议):

  • 特点: 无连接、不可靠。
  • 功能: 提供网络层的数据报服务,负责数据包的寻址和路由。IP地址用于标识网络中的主机和路由器。
  • IPv4 and IPv6IPv4是早期版本,使用32位地址;IPv6是新一代版本,采用128位地址,解决IPv4地址枯竭问题。
  • 分组: 将数据分割成小的数据包进行传输,每个包独立传输,由目标主机重新组装。

3. 协议栈层次结构:

  • 应用层: 提供网络服务的接口,包括HTTP(Web)、FTP(文件传输协议)、SMTP(简单邮件传输协议)等。
  • 传输层: 提供端到端的通信,包括TCPUDPTCP提供可靠的、面向连接的通信;UDP提供不可靠的、面向无连接的通信。
  • 网络层: 负责数据包的寻址和路由,包括IP协议。
  • 数据链路层: 负责将数据包封装成帧,并通过物理层进行传输。
  • 物理层: 硬件部分,负责实际的比特流传输。

4. 路由和子网划分:

  • 路由: 负责在网络中选择最佳路径,将数据包从源主机传输到目标主机。
  • 子网划分: 将大型网络划分成多个子网,提高网络的性能和管理效率。

5. 域名系统(DNS):

  • 功能: 将人类可读的域名翻译为计算机可理解的IP地址。
  • 层次结构: 分布式的命名系统,包括顶级域、二级域等。

网络与套接字编程

网络编程基础

1.客户端-服务器模型:

网络编程通常涉及客户端和服务器之间的通信。服务器提供服务,而客户端请求服务。

2.协议:
通信双方需要使用相同的协议进行通信,常见的包括HTTP、FTP、TCP、UDP等。

3.IP地址和端口号:
计算机在网络上通过IP地址进行标识,端口号用于标识一个具体的应用程序或服务。

4.具体实例:

使用Pythonsocket模块创建一个简单的服务器和客户端。这个例子中,服务器接收客户端的连接并返回一个简单的消息。

服务器端代码(server.py):

import socket

# 创建套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定地址和端口
server_socket.bind(('127.0.0.1', 8080))

# 监听连接
server_socket.listen(5)
print("服务器正在监听端口 8080...")

while True:
    # 等待客户端连接
    client_socket, client_address = server_socket.accept()
    print(f"接受来自 {client_address} 的连接")

    # 发送欢迎消息给客户端
    message = "欢迎连接到服务器!"
    client_socket.send(message.encode())

    # 接收客户端发送的数据
    data = client_socket.recv(1024).decode()
    print(f"客户端消息: {data}")

    # 关闭连接
    client_socket.close()

客户端代码(client.py):

import socket

# 创建套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接到服务器
client_socket.connect(('127.0.0.1', 8080))
print("已连接到服务器")

# 接收服务器发送的欢迎消息
welcome_message = client_socket.recv(1024).decode()
print(f"服务器消息: {welcome_message}")

# 发送数据给服务器
client_socket.send("你好,服务器!".encode())

# 关闭连接
client_socket.close()

套接字编程

套接字编程是一种强大的工具,用于实现各种网络应用程序,包括Web服务器、聊天应用、文件传输等

1.套接字基础:
套接字是一种用于网络通信的编程接口,支持不同协议(例如TCP、UDP)。在Python中,socket模块提供了套接字编程的接口。

import socket

2.创建套接字:
使用socket.socket()方法创建套接字,可以指定套接字的类型(SOCK_STREAM为TCP套接字,SOCK_DGRAM为UDP套接字)。

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

3.绑定和监听:
对于服务器,需要将套接字绑定到一个特定的IP地址和端口,并开始监听连接请求。

server_socket.bind(('127.0.0.1', 8080))
server_socket.listen(5)

4.接受连接:
服务器使用accept()方法等待客户端的连接请求,并返回一个新的套接字用于与客户端通信。

client_socket, client_address = server_socket.accept()

5.建立连接:
客户端使用socket.connect()方法与服务器建立连接。

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('127.0.0.1', 8080))

6.发送和接收数据:
使用套接字的send()recv()方法进行数据的发送和接收。

client_socket.send(b'Hello, server!')
data = client_socket.recv(1024)

7.关闭连接:
使用close()方法关闭套接字连接。

client_socket.close()

服务器——客户机程序

UDP回显服务器——客户机程序

服务器程序(server.c):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#define BUFLEN 256 // max length of buffer
#define PORT 1234  // fixed server port number
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");
        // recvfrom() gets client IP, port in sockaddr_in clinet
        rlen = recvfrom(sock, line, BUFLEN, 0, (struct sockaddr *)&client, &clen);
        printf("received a datagram from [host:port] = [8s:8d] \n",
               inet_ntoa(client.sin_addr), ntohs(client.sin_port));
        printf("rlen=&d: line=ts\n", rlen, line);
        printf("send reply\n");
        sendto(sock, line, rlen, 0, (struct sockaddr *)&client, clen);
    }
}

客户机程序(client.c):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>

#define SERVER_HOST "127.0.0.1" // default server IP: localhost #define SERVER_PORT 1234
#define SERVER_PORT 1234        // fixed server port number
#define BUFLEN 256              // max length of buffer

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));
    other.sin_family = AF_INET;
    other.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=8d: line=ts\n", rlen, line);
    }
}

TCP回显服务器——客户机程序

服务器程序(server.c):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>  // Added inclusion of unistd.h for close function

#define MAX 256
#define SERVER_HOST "localhost"
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 1234  // Defined SERVER_PORT here

struct sockaddr_in server_addr, client_addr;
int mysock, csock;

void server_init() {
    printf("================ server init =================\n");

    // 1. Create a TCP socket
    printf("1 : create a TCP socket\n");
    mysock = socket(AF_INET, SOCK_STREAM, 0);
    if (mysock < 0) {
        perror("socket call failed");
        exit(1);
    }

    // 2. Fill server_addr with server's IP and PORT#
    printf("2 : fill server_addr with server's IP and PORT#\n");
    memset((char*)&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // Use localhost
    server_addr.sin_port = htons(SERVER_PORT);

    // 3. Bind socket to server address
    printf("3 : bind socket to server address\n");
    int r = bind(mysock, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if (r < 0) {
        perror("bind failed");
        exit(3);
    }

    printf("hostname = %s port = %d\n", SERVER_HOST, SERVER_PORT);
    printf("4 : server is listening ....\n");
    
    // 4. Listen for incoming connections
    listen(mysock, 5); // Queue length = 5

    printf("================== init done ===============\n");
}

int main() {
    int n;
    char line[MAX];

    server_init();

    while (1) {
        // Try to accept a client request
        printf("server: accepting new connection ....\n");
        socklen_t len = sizeof(client_addr);
        csock = accept(mysock, (struct sockaddr*)&client_addr, &len);
        if (csock < 0) {
            perror("server: accept error");
            exit(1);
        }

        printf("server: accepted a client connection from\n");
        printf("Client: IP=%s port=%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        // Processing loop: client_sock <== data ==> client
        while (1) {
            n = recv(csock, line, MAX, 0);
            if (n <= 0) {
                printf("server: client closed the connection, server loops\n");
                close(csock);
                break;
            }

            // Show the received line string
            printf("server: received n=%d bytes; line=%s\n", n, line);

            // Echo line to client
            n = send(csock, line, n, 0);
            printf("server: sent n=%d bytes; echo=%s\n", n, line);
        }
    }

    return 0;
}

客户机程序(client.c):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h> // Added inclusion of arpa/inet.h for bzero function

#define MAX 256
#define SERVER_HOST "localhost"
#define SERVER_PORT 1234

struct sockaddr_in server_addr;
int sock, r;

int client_init() {
    printf("================ client init =================\n");

    // 1. Create a TCP socket
    printf("1 : create a TCP socket\n");
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket call failed");
        exit(1);
    }

    // 2. Fill server_addr with server's IP and PORT#
    printf("2 : fill server_addr with server's IP and PORT#\n");
    memset((char*)&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // Use localhost
    server_addr.sin_port = htons(SERVER_PORT);

    // 3. Connect to server
    printf("3 : connecting to server ...\n");
    r = connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if (r < 0) {
        perror("connect failed");
        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);
    }

    return 0;
}

Web和CGI编程

Web编程和CGI(通用网关接口)编程都是与构建Web应用程序相关的技术,它们使得服务器端能够处理来自客户端的请求,并生成动态的Web页面。

Web编程

Web编程涉及创建Web应用程序,通过HTTP协议与客户端进行通信。在这里使用Python的内置模块http.server来创建一个简单的Web服务器。

# 文件名: web_server.py
import http.server
import socketserver

# 定义处理请求的处理程序
handler = http.server.SimpleHTTPRequestHandler

# 创建服务器并指定端口
port = 8000
httpd = socketserver.TCPServer(("", port), handler)

print(f"Serving on port {port}")
# 启动服务器
httpd.serve_forever()

在终端运行这个脚本,然后在浏览器中访问http://localhost:8000,将看到一个简单的文件浏览页面。

CGI编程

CGI允许Web服务器调用外部程序来处理Web请求,这使得能够动态生成Web页面。在这个例子中,我们创建一个简单的CGI脚本,用于处理Web请求。

# 文件名: cgi_script.py
#!/usr/bin/env python

print("Content-type: text/html\n")
print("<html><body>")
print("<h1>Hello CGI!</h1>")
print("</body></html>")

确保给cgi_script.py添加可执行权限。然后,修改web_server.py,使其支持CGI:

# 文件名: web_server_cgi.py
import http.server
import socketserver
import cgi

# 使用CGI处理程序
handler = http.server.CGIHTTPRequestHandler
handler.cgi_directories = ["/cgi-bin"]

# 创建服务器并指定端口
port = 8001
httpd = socketserver.TCPServer(("", port), handler)

print(f"Serving on port {port}")
# 启动服务器
httpd.serve_forever()

实践过程

UDP回显服务器——客户机程序


TCP回显服务器——客户机程序


Web编程与CGI编程

GPT挑战




posted @ 2023-11-24 11:11  沈楗翔  阅读(7)  评论(0编辑  收藏  举报