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
框架如Flask
和Django
都包含了网络编程的支持。 -
异步编程: 随着网络应用的复杂性增加,异步编程变得越来越重要。异步编程允许程序在等待网络数据的同时执行其他任务,提高了程序的效率和响应性。例如,
Python
中的asyncio
库提供了异步编程的支持。
TCP/IP协议
TCP/IP协议是一组用于互联网通信的协议,它是网络世界中最基础、最重要的协议之一。TCP/IP指的是传输控制协议(TCP)和因特网协议(IP),它们共同构成了一个层次化的协议栈。
1. TCP(传输控制协议):
- 特点: 面向连接、可靠、基于字节流。
- 功能: 提供可靠的数据传输服务,确保数据的有序性和完整性。通过流控制、拥塞控制等机*制来维护网络通信的稳定性。
- 连接: 在通信之前,需要通过三次握手建立连接,以及四次握手来终止连接。
- 流量控制: 通过滑动窗口机制控制发送方的发送速率,防止接收方来不及处理过多的数据。
- 拥塞控制: 避免在网络拥塞时导致性能下降,通过动态调整传输速率来维护网络的健康状态。
2. IP(因特网协议):
- 特点: 无连接、不可靠。
- 功能: 提供网络层的数据报服务,负责数据包的寻址和路由。IP地址用于标识网络中的主机和路由器。
IPv4
andIPv6
:IPv4
是早期版本,使用32位地址;IPv6
是新一代版本,采用128位地址,解决IPv4地址枯竭问题。- 分组: 将数据分割成小的数据包进行传输,每个包独立传输,由目标主机重新组装。
3. 协议栈层次结构:
- 应用层: 提供网络服务的接口,包括
HTTP
(Web)、FTP
(文件传输协议)、SMTP
(简单邮件传输协议)等。 - 传输层: 提供端到端的通信,包括
TCP
和UDP
。TCP
提供可靠的、面向连接的通信;UDP
提供不可靠的、面向无连接的通信。 - 网络层: 负责数据包的寻址和路由,包括IP协议。
- 数据链路层: 负责将数据包封装成帧,并通过物理层进行传输。
- 物理层: 硬件部分,负责实际的比特流传输。
4. 路由和子网划分:
- 路由: 负责在网络中选择最佳路径,将数据包从源主机传输到目标主机。
- 子网划分: 将大型网络划分成多个子网,提高网络的性能和管理效率。
5. 域名系统(DNS):
- 功能: 将人类可读的域名翻译为计算机可理解的IP地址。
- 层次结构: 分布式的命名系统,包括顶级域、二级域等。
网络与套接字编程
网络编程基础
1.客户端-服务器模型:
网络编程通常涉及客户端和服务器之间的通信。服务器提供服务,而客户端请求服务。
2.协议:
通信双方需要使用相同的协议进行通信,常见的包括HTTP、FTP、TCP、UDP等。
3.IP地址和端口号:
计算机在网络上通过IP地址进行标识,端口号用于标识一个具体的应用程序或服务。
4.具体实例:
使用
Python
的socket
模块创建一个简单的服务器和客户端。这个例子中,服务器接收客户端的连接并返回一个简单的消息。
服务器端代码(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挑战
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
2021-11-24 小学四则运算编程实现(必做)