一、任务要求
[ 1 ] 知识点归纳以及自己最有收获的内容,选择至少2个知识点利用chatgpt等工具进行苏格拉底挑战,并提交过程截图,提示过程参考下面内容 (4分)
我在学****知识点,请你以苏格拉底的方式对我进行提问,一次一个问题
核心是要求GPT:请你以苏格拉底的方式对我进行提问
然后GPT就会给你提问,如果不知道问题的答案,可以反问AI:你的理解(回答)是什么?
如果你觉得差不多了,可以先问问GPT:针对我XXX知识点,我理解了吗?
GPT会给出它的判断,如果你也觉得自己想清楚了,可以最后问GPT:我的回答结束了,请对我的回答进行评价总结,让它帮你总结一下。
[ 2 ] 问题与解o决思路,遇到问题最先使用chatgpt等AI工具解决,并提供过程截图(3分)
[ 3 ] 实践过程截图,代码链接(2分)
[ 4 ] 其他(知识的结构化,知识的完整性等,提交markdown文档,使用openeuler系统等)(1分)
二、知识点总结
TCP/IP协议
TCP/IP堆栈
- 顶层是使用TCP/IP的应用程序。用于登录到远程主机的ssh、用于交换电子邮件的mail、用于Web界面的http等应用程序需要可靠的数据传输。
- 不需要可靠性的应用程序可以在传输层使用UDP来提高效率。
- 传输层负责以包的形式向IP 主机发送/接收来自IP 主机的应用程序数据。进程与主机之间的传输层或其上方的数据传输只是逻辑传输。实际数据传输发生在互联网(IP)和链路层,这些层将数据包分成数据帧,以便在物理网络之间传输。
IP主机和IP地址
- 主机是支持TCP/IP协议的计算机或设备,每个主机由一个32位的IP地址来表示。通常使用点记法。
- IP地址分为networkID字段和hostID字段
IP数据包格式
路由器
TCP/IP网络拓扑结果:
每个IP包在IP包头中都有一个8位生存时间(TTL),最大值位255,每经过一个路由器,TTL减一,TTL减小到0,包会被丢弃,,如此可以防止数据包在IP网络中无限循环。
UDP和TCP
- UDP:在IP上运行,用于发送/接收数据报。与IP 类似,UDP不能保证可靠性,但是快速高效。它可用于可靠性不重要的情况例如,用户可以使用ping命令探测目标主机
- TCP:TCP(传输控制协议)是一种面向连接的协议,用于发送/接收数据流。TCP也可在IP上运行,但它保证了可靠的数据传输。通常,UDP类似于发送邮件的USPS,而TCP类似于电话连接。
端口编号
在各主机中,多个应用程序可同时使用TCP/UDP,每个应用程序可由三个组成部分唯一表示:应用程序=(主机IP, 协议, 端口号),协议是TCP/UDP,端口号是分配给应用程序的唯一无符号短整数。
使用TCP的常见应用程序及其端口号:
网络和主机字节序
- 大端:高位字节存入低地址,低位字节存入高地址
- 小端:低位字节存入低地址,高位字节存入高地址
TCP/IP网络中的数据流
套接字编程
套接字地址
struct sockaddr_in {
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
};
struct in_addr {
uint32_t s_addr;
}
套接字API
1. int套接字
int udp_sock = socket(AF_INET, SOCK_DGRAM, 0); //将会创建一个用于发送/接收UDP数据报的套接字。
int tcp_sock = socket(AF_INET, SOCK_STREAM, 0); //将会创建一个用于发送/接收数据流的面向连接的TCP套接
字c
2.int bind
int bind(int sockfd, struct sockaddr *addr, socklen_t addrlen)
bind()系统调用将addr指定的地址分配给文件描述符sockfd所引用的套接字addrlen 指定addr所指向地址结构的大小(以字节为单位)。对于用于联系其他UDP服务器主机的UDP套接字,必须绑定到客户机地址,允许服务器发回应答。对于用于接收客户机连接的TCP套接字,必须先将其绑定到服务器主机地址。
3.UDP套接字
UDP套接字使用sendto()/recvfrom()来发送/接受数据报
4.TCP套接字
在创建套接字并将其绑定到服务器地址之后,TCP服务器使用listen()和acccpt()来接 收来自客户机的连接
int Iistcn(int sockfd, int backlog);
listen()将sockfd引用的套接字标记为将用于接收连入连接的套接字。backlog参数定义了等 待连接的最大队列长度。
int accept(int sockfd, struct sockaddr *addr, sockien_t *addrlen);
accept()系统调用与基于连接的套接字一起使用。它提取等待连接队列上的第一个连接请求 用于监听套接字sockfd,创建一个新的连接套接字,并返回一个引用该套接字的新文件描 述符,与客户机主机连接。在执行accept()系统调用时,TCP服务器阻塞,直到客户机通过 coimectO建立连接。
int connect(int sockfd, const struct sockaddr *addr, socklen t addrlen);
connect()系统调用将文件描述符sockfd引用的套接字连接到addr指定的地址,addrlen参数 指定addr的大小。addr中的地址格式由套接字sockfd的地址空间决定。
如果套接字sockfd是SOCK_DGRAM类型,即UDP套接字,addr是发送数据报的默 认地址,也是接收数据报的唯一地址。这会限制UDP套接字与特定UDP主机的通信,但实际上很少使用。所以对于UDP套接字来说,连接是可选的或不必要的。如果套接字是 SOCK_STREAM类型,即TCP套接字。
三、苏格拉底挑战
四、实践
UDP回显服务器——客户机程序
服务器
#include <stdio.h>
#include<stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#define BUFLEN256
#define PORT1234
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 portln");
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: ine=s\n",rlen,line);printf("send reply\n");
sendto(sock,line,rlen,0,(struct sockaddr*)&client,clen);
}
}
客户机
#include<stdio.h>
#include<stalib.h>
#include<string.h>
#include<sys/socket.h>
#include <netinet/ip.h>
#define SERVER_HOST"127.0.0.1"
#define SERVER PORT1234
#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));
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");
gendto(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);
}
}
TCP回显服务器——客户机程序
服务器:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.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;
void server_init() {
printf("================ server init =================\n");
printf("1 : create a TCP socket\n");
mysock = socket(AF_INET, SOCK_STREAM, 0);
if (mysock < 0) {
perror("socket call failed");
exit(1);
}
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);
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) {
perror("bind failed");
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() {
int n;
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) {
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));
while (1) {
n = recv(csock, line, MAX, 0);
if (n <= 0) {
printf("server: client closed the connection, server loops\n");
close(csock);
break;
}
printf("server: received n=%d bytes; line=%s\n", n, line);
n = send(csock, line, n, 0);
printf("server: sent n=%d bytes; echo=%s\n", n, line);
}
}
return 0;
}
客户机:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#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");
printf("1 : create a TCP socket\n");
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket call failed");
exit(1);
}
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);
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);
fgets(line, MAX, stdin);
line[strlen(line) - 1] = '\0';
if (line[0] == '\0')
exit(0);
n = write(sock, line, MAX);
printf("client: wrote n=%d bytes; line=%s\n", n, line);
n = read(sock, ans, MAX);
printf("client: read n=%d bytes; echo=%s\n", n, ans);
}
return 0;
}
标签:addr,TCP,server,20211316,郭佳昊,printf,line,接字
From: https://www.cnblogs.com/GJH6/p/17852148.html