20211306 密码系统设计与实现课程学习笔记11
任务详情
自学教材第13章,提交学习笔记
- 知识点归纳以及自己最有收获的内容,选择至少2个知识点利用chatgpt等工具进行苏格拉底挑战,并提交过程截图,提示过程参考下面内容
“我在学***X知识点,请你以苏格拉底的方式对我进行提问,一次一个问题”
核心是要求GPT:“请你以苏格拉底的方式对我进行提问”
然后GPT就会给你提问,如果不知道问题的答案,可以反问AI:“你的理解(回答)是什么?”
如果你觉得差不多了,可以先问问GPT:“针对我XXX知识点,我理解了吗?”
GPT会给出它的判断,如果你也觉得自己想清楚了,可以最后问GPT:“我的回答结束了,请对我的回答进行评价总结”,让它帮你总结一下。
- 问题与解决思路,遇到问题最先使用chatgpt等AI工具解决,并提供过程截图
- 实践过程截图,代码链接
- 其他(知识的结构化,知识的完整性等,提交markdown文档,使用openeuler系统等)
一、第十三章学习总结
摘要
本章论述了TCP/IP 和网络编程,分为两个部分。第一部分论述了TCP/IP 协议及其应用,具体包括TCP/IP栈、IP地址、主机名、DNS、IP数据包和路由器:介绍了TCP/IP 网络中的UDP和TCP协议、端口号和数据流;阐述了服务器-客户机计算模型和套接字编程接口;通过使用UDP和TCP套接字的示例演示了网络编程。
本章的第二部分介绍了 Web和CGI编程解释了HTTP编模型Web页面和Web浏览器:展示了如何配置LinuxHTTPD服务器来支持用户Web页面PHP和CGI编程:阐释了客户机和服务器端动态Web页面:示了如何使用PHP和CGI创建服务器端动态Web页面。
网络编程简介
TCP/IP协议
TCP 代表传输控制协议。IP代表互联网协议。目前有两个版本的IP,即IP4和IPV6。IP4 使用32位地址,IPv6则使用128位地址。
顶层是使用TCP/IP 的应用程序。用于登录到远程主机的 ssh、用于交换电子邮件的mail、用于 Web 页面的 http 等应用程序需要可靠的数据传输。通常,这类应用程序在传输层使用TCP。另一方面,有些应用程序,例如用于查询其他主机的 ping命令,则不需要可靠性。
传输层负责以包的形式向 IP 主机发送/接收来自IP 主机的应用程序数据。进程与主机之间的传输层或其上方的数据传输只是逻辑传输。实际数据传输发生在互联网(IP)和链路层,这些层将数据包分成数据帧,以便在物理网络之间传输。
IP主机和IP地址
主机是支持TCP/IP 协议的计算机或设备。每个主机由一个32位的IP地址来标识。
IP地址分为两部分,即NetworkID 字段和HostID 字段。
IP协议
IP 协议用于在IP 主机之间发送/接收数据包。IP 尽最大努力运行。IP 主机只向接收主机发送数据包,但它不能保证数据包会被发送到它们的目的地,也不能保证按顺序发送。这意味着 IP 并非可靠的协议。必要时,必须在IP 层的上面实现可靠性。
IP数据包格式
IP 数据包由 IP 头、发送方P 地址和接收方IP 地址以及数据组成。每个IP 数据包的大小最大为 64KB。IP 头包含有关数据包的更多信息,例如数据包的总长度、数据包使用TCP还是UDP、生存时间(TTL)计数、错误检测的校验和等。
路由器
IP 主机之间可能相距很远。通常不可能从一个主机直接向另一个主机发送数据包。路由器是接收和转发数据包的特殊IP主机。如果有的话一个IP数据包可能会经过许多路由器,或者跳跃到达某个目的地。每个IP包在IP报头中都有一个8位生存时间(TTL)计数,其最大值为255。在每个路由器上,TTL会减小1。如果 TTL减小到0,而包仍然没有到达目的地,则会直接丢弃它。这可以防止任何数据包在IP网络中无限循环。
UDP
UDP(用户数据报协议)在IP上运行用于发送/接收数据报。与IP类似,UDP不能保证可靠性,但是快速高效。它可用于可靠性不重要的情况。
ping主机名或pingIP地址
ping是一个向目标主机发送带时间戳UDP包的应用程序。接收到一个pinging数据包后,目标主机将带有时间戳的UDP 包回送给发送者,让发送者可以计算和显示往返时间。如果目标主机不存在或宕机,当TTL减小为0时,路由器将会丢弃pinging UDP数据包在这种情况下,用户会发现目标主机没有任何响应。用户可以尝试再次 ping,或者断定目标主机宕机。在这种情况下,最好使用UDP,因为不要求可靠性。
TCP
TCP(传输控制协议)是一种面向连接的协议,用于发送/接收数据流。TCP也可在IP上运行,但它保证了可靠的数据传输。通常,UDP类似于发送邮件的USPS,而TCP类似于电话连接。
端口编号
在各主机上,多个应用程序(进程)可同时使用TCP/UDP。每个应用程序由三个组成部分唯一标识
网络和主机字节序
计算机可以使用大端字节序,也可以使用小端字节序。在互联网上,数据始终按网络序排列,这是大端。在小端机器上,例如基于Intelx86的PC,htons0、htonl0、ntohs0)ntohl0等库函数,可在主机序和网络序之间转换数据。
TCP/IP网络中的数据流
应用程序层的数据被传递到传输层,传输层给数据添加一个TCP或UDP报头来标识使用的传输协议。合并后的数据被传递到IP 网络层,添加一个包含 IP 地址的IP报头来标识发送和接收主机。然后,合并后的数据再被传递到网络链路层,网络链路层将数据分成多个帧,并添加发送和接收网络的地址,用于在物理网络之间传输。IP 地址到网络地址的映射由地址解析协议(ARP)执行(ARP1982)。在接收端,数据编码过程是相反的每一层通过剥离数据头来解包接收到的数据,重新组装数据并将数据传递到上一层。发送主机上的应用程序原始数据最终会被传递到接收主机上的相应应用程序。
网络编程
- 网络编程平台
- 服务器-客户机计算模型
大多数网络编程任务都基于服务器-客户机计算模型。在服务器-客户机计算模型中我们首先在服务器主机上运行服务器进程。然后,我们从客户机主机运行客户机。在UDP中,服务器等待来自客户机的数据报,处理数据报并生成对客户机的响应。在 TCP 中,服务器等待客户机连接。客户机首先连接到服务器,在客户机和服务器之间建立一个虚拟电路。建立连接后,服务器和客户机可以交换连续的数据流。
套接字编程
- 套接字地址
- 套接字API
UDP回显服务器-客户机程序
- server
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.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. 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);
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);
}
return 0;
}
- client
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> // Added inclusion of arpa/inet.h for inet_aton function
#define SERVER_HOST "127.0.0.1" // Default server IP: localhost
#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));
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'; // Fixed newline character removal
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;
}
TCP回显服务器-客户及程序
- server
#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_PORT 1234
int mysock, csock;
struct sockaddr_in server_addr, client_addr;
int server_init()
{
printf("================== server init =====================\n");
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");
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(SERVER_PORT);
printf("3 : bind socket to server address\n");
int 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);
printf("================ init done ===========================\n");
}
int main()
{
char line[MAX];
server_init();
while (1) {
printf("server: accepting new connection ....\n");
socklen_t 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(*(struct in_addr*)&client_addr.sin_addr.s_addr), ntohs(client_addr.sin_port));
printf("----------------------------\n");
while (1) {
int n = read(csock, line, MAX);
if (n <= 0) {
printf("server: client died, server loops\n");
close(csock);
break;
}
line[n] = '\0'; // Ensure null-terminated string
printf("server: read n=%d bytes; line=%s\n", n, line);
n = write(csock, line, n);
printf("server: wrote n=%d bytes; ECHO=%s\n", n, line);
printf("server: ready for next request\n");
}
}
}
- client
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#define MAX 256
#define SERVER_HOS "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_HOS,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);
fgets(line,MAX,stdin);
line[strlen(line)-1] = 0;
if (line[0]==0)
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);
}
}
主机名和IP地址
Web和CGI编程
- HTTP编程模型
- Web页面
- Web页面配置HTTPD
- 动态Web页面
- PHP
二、苏格拉底挑战GPT
三、代码实现
四、问题解决
在进行TCP回显服务器-客户机程序时,书中的代码无法进行连接,会出现段错误,提问chatgpt后完善了代码