是TC

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一、学习任务

自学教材第13章,提交学习笔记(10分),评分标准如下

1. 知识点归纳以及自己最有收获的内容,选择至少2个知识点利用chatgpt等工具进行苏格拉底挑战,并提交过程截图,提示过程参考下面内容 (4分)

“我在学***X知识点,请你以苏格拉底的方式对我进行提问,一次一个问题”

核心是要求GPT:“请你以苏格拉底的方式对我进行提问” 然后GPT就会给你提问,如果不知道问题的答案,可以反问AI:“你的理解(回答)是什么?”

如果你觉得差不多了,可以先问问GPT:“针对我XXX知识点,我理解了吗?” GPT会给出它的判断,如果你也觉得自己想清楚了,可以最后问GPT:“我的回答结束了,请对我的回答进行评价总结”,让它帮你总结一下。

2. 问题与解决思路,遇到问题最先使用chatgpt等AI工具解决,并提供过程截图(3分)

3. 实践过程截图,代码链接(2分)

4. 其他(知识的结构化,知识的完整性等,提交markdown文档,使用openeuler系统等)(1分)

二、知识总结

摘要

本章论述了TCP/IP 和网络编程,分为两个部分。第一部分论述了TCP/IP 协议及其应 用,具体包括TCP/IP 栈 、IP 地址、主机名、DNS 、IP 数据包和路由器;介绍了TCP/IP 网 络中的 UDP 和 TCP 协议、端口号和数据流;阐述了服务器-客户机计算模型和套接字编程 接口;通过使用UDP 和 TCP 套接字的示例演示了网络编程。第一个编程项目可实现一对通 过互联网执行文件操作的 TCP 服务器-客户机,可让用户定义其他通信协议来可靠地传输 文件内容。
本章的第二部分介绍了Web 和 CGI 编程,解释了HTTP 编程模型、Web 页面和 Web 浏 览器;展示了如何配置Linux HTTPD 服务器来支持用户Web页面、PHP 和 CGI 编程;阐 释了客户机和服务器端动态Web 页面;演示了如何使用PHP 和 CGI 创建服务器端动态Web 页面。第二个编程项目可让读者在Linux HTTPD 服务器上通过CGI 编程实现服务器端动态 Web页面。

13.1TCP/IP协议

TCP 代表传输控制协议。 IP 代表互联网协议。目前有两个版本的IP,   即 IPv4 和 IPv6 。IPv4 使用32位地址, IPv6 则  使用128位地址。

TCP/IP的组织结构分为几个层级,通常称为TCP/IP 堆栈。

 

顶层是使用TCP/IP 的应用程序。用于登录到远程主机的ssh 、用于交换电子邮件的mail 、用于Web页面的http 等应用程序需要可靠的数据传输。通常,这类应用程序在传输 层使用TCP。另一方面,有些应用程序,例如用于查询其他主机的 ping 命令,则不需要可 靠性。这类应用程序可以在传输层使用UDP 来提高效率 (RFC  7681980;Comer  1988)。传输层负责以包的形式向IP 主机发送/接收来自IP 主机的应用程序数据。进程与主机之间的 传输层或其上方的数据传输只是逻辑传输。实际数据传输发生在互联网(IP) 和链路层。

 13.2ip主机和地址

主机是支持TCP/IP 协议的计算机或设备。每个主机由一个32位的 IP 地址来标识。实际上,应用程序通常使用主机名而不是IP 地址。在这个意义上说,主机名就等同于IP地址。

IP 地址分为两部分,即NetworkID 字段和HostID 字段。根据划分,IP 地址分为A~E  类。例如, 一个B 类 IP 地址被划分为一个16位NetworkID,  其中前2位是10,然后是一16位的HostID字段。发往IP 地址的数据包首先被发送到具有相同networkID 的路由器。 路由器将通过HostID将数据包转发到网络中的特定主机。每个主机都有一个本地主机名 localhost,   默认IP 地址为127.0.0.1。本地主机的链路层是一个回送虚拟设备,它将每个数 据包路由回同一个localhost 。这个特性可以让我们在同一台计算机上运行TCP/IP 应用程序, 而不需要实际连接到互联网。

13.3ip协议与数据包格式

IP协议用于在IP主机之间发送/接收数据包。IP 数据包由IP头、发送方IP 地址和接收方IP 地址以及数据组成。每个IP 数据包的大 小最大为64KB 

 13.4路由器

路由器是接收和转发数据包的特殊IP主机。

每个IP包在IP报头中都有一个8位生存时间 (TTL) 计数,其最大值为255。在每个路由器上,TTL会减小1。如果TTL减小到0,而包仍然没有到达目的地,则会直接丢弃它。

13.5udp和tcp

UDP(用户数据报协议)在IP上运行,用于发送/接收数据报。

TCP (传输控制协议)是一种面向连接的协议,用于发送/接收数据流。

13.6端口编号

在各主机上,多个应用程序(进程)可同时使用TCP/UDP 。 每个应用程序由三个组成部分唯一标识

应用程序=(主机 IP,  协议,端口号)

其中,协议是TCP或UDP,端口号是分配给应用程序的唯一无符号短整数。要想使用 UDP或TCP,应用程序(进程)必须先选择或获取一个端口号。前1024个端口号已被预留。其他端口号可供一般使用。应用程序可以选择一个可用端口号,也可以让操作系统内核分配 端口号。下图给出了在传输层中使用TCP的一些应用程序及其默认端口号。

 13.7网络和主机字节序

计算机可以使用大端字节序,也可以使用小端字节序。在互联网上,数据始终按网络 序排列,这是大端。在小端机器上,例如基于Intelx86  的 PC,htons() 、htonl() 、ntohs()、ntohs() 等库函数,可在主机序和网络序之间转换数据。例如,PC 中的端口号1234按主机字 节序(小端)是无符号短整数。必须先通过htons(1234)把它转换成网络序,才能使用。相反,从互联网收到的端口号必须先通过 ntohs(port) 转换为主机序。

13.8TCP/IP网络中的数据流

应用程序层的数据被传递到传输层,传输层给数据添加一个TCP或 UDP  报头来标识使用的传输协议。合并后的数据被传递到IP 网络层,添加一个包含IP 地址的IP  报头来标识发送和接收主机。然后,合并后的数据再被传递到网络链路层,网络链路层将数 据分成多个帧,并添加发送和接收网络的地址,用于在物理网络之间传输。IP 地址到网络 地址的映射由地址解析协议(ARP)  执行(ARP1982)。  在接收端,数据编码过程是相反的。 每一层通过剥离数据头来解包接收到的数据,重新组装数据并将数据传递到上一层。发送主  机上的应用程序原始数据最终会被传递到接收主机上的相应应用程序。

13.9网络编程

要进行网络编程,读者必须能够访问支持网络编程的平台。

大多数网络编程任务都基于服务器-客户机计算模型。服务器-客户机计算模型中, 我们首先在服务器主机上运行服务器进程。然后,我们从客户机主机运行客户机。在 UDP   中,服务器等待来自客户机的数据报,处理数据报并生成对客户机的响应。在TCP中,服  务器等待客户机连接。客户机首先连接到服务器,在客户机和服务器之间建立一个虚拟电  路。建立连接后,服务器和客户机可以交换连续的数据流。

13.10

在网络编程中,TCP/IP的用户界面是通过一系列C 语言库函数和系统调用来实现的, 这些函数和系统调用统称为套接字API ((Rago   1993;Stevens 2004)。为了使用套接字 API,   我们需要套接字地址结构,它用于标识服务器和客户机。netdb.h和 sys/socket.h 中有 套接字地址结构的定义。

13.10.1套接字地址

struct


);
struct
};


套接字地址
sockaddr_in   (
sa_family_t   sin_family;   //AF_INET for TCP/IP
in_port_t    sin_port;      //port     number
struct    in_addr    sin_addr;//IP    address
in_addr(                       //internet       address
uint32_t         s_addr;           //IP  address  in  network  byte   order

 

在套接字地址结构中,

●TCP/IP   网络的sin_family始终设置为 AF_INET
sin_port 包含按网络字节顺序排列的端口号。
●sin_addr是按网络字节顺序排列的主机IP地址。

13.10.2  套接字 API

服务器必须创建一个套接字,并将其与包含服务器IP 地址和端口号的套接字地址绑 定。它可以使用一个固定端口号,或者让操作系统内核选择一个端口号(如果sin_port为 0)。为了与服务器通信,客户机必须创建一个套接字。对于UPD套接字,可以将套接字绑 定到服务器地址。如果套接字没有绑定到任何特定的服务器,那么它必须在后续的 sendtoO)/ recvfrom()调用中提供一个包含服务器IP和端口号的套接字地址。下面给出了socket()系统  调用,它创建一个套接字并返回一个文件描述符

1.int  套接字(int 域,int 类型, int 协议)

2.int  bind(int  sockfd,struct  sockaddr  *addr,socklen_t  addrlen)

3.UDP 套接字

UDP套接字使用 sendto()/recvfrom()来发送/接收数据报。

ssize_t   sendto(int   sockfd,congt   void    *buf,size_t   len,int   flags,
const struct sockaddr *dest_addr,socklen_t addrlen);
ssize_t   recvfrom(int    sockfd,void   *buf,size_t    len,int   flags,
struct sockaddr *sre_addr,socklen_t *addrlen);

sendto()将缓冲区中的len 字节数据发送到由 dest_addr标识的目标主机,该目标主机包 含目标主机IP 和端口号。recvfrom()从客户机主机接收数据。除了数据之外,它还用客户机 的 IP和端口号填充sre_addr, 从而允许服务器将应答发送回客户机。

4.TCP 套接字

在创建套接字并将其绑定到服务器地址之后, TCP 服务器使用listen() 和 accept() 来接 收来自客户机的连接

int listen(int sockfd,int backlog);

int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);

13.11UDP回显服务器-客户机程序

#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);
    printE("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",
ohs(client.sin_port));
printf("send reply\n");
sendto(sock,line,rlen,0,(struct             sockaddr*)&client,clen);
}
)
/*****C13.1.b:UDP client.c file *****/
#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      //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  :");
gii,sntdein)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(gock,line,BUFLEN,0,(struct sockaddr*)&server,&slen);
printf("rlen=%d:line=8s\n",rlen,line);

输出示例

 

 13.12UDP回显服务器-客户机程序

/********C13.2.a:TCP server.c File ********/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.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;             //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 IF  server_addr.sin_port =htons(SERVER_PORT);    //port   number   1234
,( skas&r,sizeof(server_addr)):
printf("bind  failed\n");exit(3);
rintf("         hostname =8sport =8d\n",SERVER_HOST,SERVER_PORT);
printf("4:server   is   listening   ..\n");
printf("===================init done ===============         =\n");

int main()
{
char line[MAX];
server_init();
while(1)(     //Try  to  accept  a  client  request
printf("server:accepting     new     connection      ..\n");
//Try  to   accept  a  client  connection  as  descriptor  newsock
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");
(-----------------\n");
inet_ntoa(client_addr.sin_addr.s_addr),
ntohs(client_addr.sin_port));
printf("--------------------------------------------\n")
//Processing    loop:client_sock    <==data     ==>client
while(1)(
(csock,line,MAX);
printf("server:client died,server loops\n");
close(csock);


break;
}
//show  the  line  string
printf("server:read       n=8d        bytes;line=8s\n",n,line);
rcsk,Ax);
printf("server:wrote    n=8d    bytes;ECHO=8s\n",n,line);
printf("server:ready   for   next    request\n");
}
}
1********C13.2.b:TCP client.c file TCP ********/
#include <stdio.h>
#include <stdlib.h>
#include  <string.h>
#include <sys/socket.h>
#include <netdb.h>
#define MAX               256
#define SERVER_HOST "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 s 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=8s PORT=8d\n",  SERVER_HOST,SERVER_PORT);
-----------------\n");
}
int main()
(
int n;


char line[MAX],ans[MAX];
client_init();
printf("******** processing 1oop *********\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
i(=Xd; bytes;line=8s\n",n,line);
//Read a line  from  sock  and  show  it
n  =read(sock,ans,MAX);
printf("client:read        n=8d         bytes;echo=8s\n",n,ans);
}

输出示例

13.13主机名和ip地址

如果读者打算在不同的主机上运行服务器和客户机,服务器端 口号由操作系统内核分配,则需要知道服务器的主机名或IP 地址及其端口号。如果某台计 算机运行 TCP/IP,  它的主机名通常记录在/etc/hosts 文件中。

下面的代码段展示了如何使用 gethostbyname()和 getsockname()来获取服务器 IP地址 和端口号(若是动态分配)。

//1.gethostname(),gethostbyname()
gethostname(myname,64);
  *hp s gethostbyname(myname);
printf("unknown     host     8s\n",myname);exit(1);
}
//2,initialize the server_addr structure
server_addr.sin_family =AF_INET;      //for TCP/IP
server_addr,sin_addr.s_addr=*(1ong *)hp->h_addr;
server_addr.sin_port =0;//let kernel assign port number
//3.create a TCP socket
int mysock =socket(AF_INET,SOCK_STREAM,0);
//4.bind  socket  with  server_addr
bind(mysock,(struct  sockaddr  *)&server_addr,sizeof(Berver_addr));
//5,get  socket  addr  to  show  port  number  assigned  by  kernel
getsockname(mysock,(struct sockaddr *)&name_addr,&length);
//6,show  server  host  name  and  port  number



printf("hostname=%s IP=8s port=8d\n",hp->h_name,
inet_ntoa(*(long      *)hp->h_addr),ntohs(name_addr.sin_port));
/*********TCP client code *********/
//run   as   client server_name server_port
struct   sockaddr_in   server_addr,sock_addr;
//1.  get server IP by name
struct hostent *hp =gethostbyname(argv[1]);
SERVER_IP     =*(1ong        *)hp->h_addr;
SERVER_PORT                   =atoi(argv[2]);
//2.create TCP socket
int sock =socket(AF_INET,SOCK_STREAM,0);
//3.fill  server_addr  with  server  IP  and  PORT#
server_addr.sin_family =AF_INET;
server_adar.sin_addr.s_addr =SERVER_IP;
server_addr,sin_port =htons(SERVER_PORT);
//4.connect    to    server
connect(sock,(struct sockaddr *)&server_addr,sizeof(server_addr));

三、苏格拉底问答

 

 

 

 

 

 

 

 

posted on 2023-11-23 17:23  是TC  阅读(20)  评论(0)    收藏  举报