《Unix/Linux系统编程》第十一周学习笔记
《Unix/Linux系统编程》第十一周学习笔记
TCP/IP协议
- TCP/IP 是互联网的基础。TCP代表传输控制协议。IP代表互联网协议。目前有两个版本的IP,即IPv4和IPv6。IPv4使用32位地址,IPv6则使用128位地址。
TCP/IP的组织结构分为几个层级,通常称为TCP/IP堆栈。
- 顶层是使用TCP/IP的应用程序。用于登录到远程主机的ssh、用于交换电子邮件的邮件、用于Web页面的http等应用程序需要可靠的数据传输。通常,这类应用程序在传输层使用TCP。另一方面有些应用程序,例如用于查询其他主机的ping命令,则不需要可靠性。这类应用程序可以在传输层使用UDP来提高效率。
- 主机:主机是支持TCP/IP协议的计算机或设备。每个主机由一个32位的IP地址来标识。
- IP地址:分为两部分,即NetworkID字段和HostID字段。根据划分,IP地址分为A~E类。例如,一个B类P地址被划分为一个16位NetworkID,其中前2位是10,然后是一个16位的HostID字段。发往P地址的数据包首先被发送到具有相同networkID 的路由器。路由器将通过HostID将数据包转发到网络中的特定主机。每个主机都有一个本地主机名localhost,默认P地址为127.0.0.1。本地主机的链路层是一个回送虚拟设备,它将每个数据包路由回同一个 localhost。
- IP协议:用于在IP主机之间发送/接收数据包。IP尽最大努力运行。IP主机只向接收主机发送数据包,但它不能保证数据包会被发送到它们的目的地,也不能保证按顺序发送。
- IP数据包:由IP头、发送方地址和接收方IP地址以及数据组成。
- IP数据包格式:每个数据包的大小最大为64KB。IP头包含有关数据包的更多信息,例如数据包的总长度、数据包使用TCP还是UDP、生存时间(TTL)计数、错误检测的校验和等。
- 路由器:接收和转发数据包的特殊IP主机。一个IP数据包可能会经过许多路由器,或者跳跃到达某个目的地。每个IP包在IP报头中都有一个8位生存时间(TTL)计数,其最大值为255。在每个路由器上,TTL会减小1。如果TTL减小到0,而包仍然没有到达目的地,则会直接丢弃它。这可以防止任何数据包在IP网络中无限循环。
- UDP:在IP上运行,用于发送/接收数据报。与IP类似,UDP不能保证可靠性,但是快速高效。
如ping是一个向目标主机发送带时间戳UDP包的应用程序。接收到一个pinging数据包后,目标主机将带有时间戳的UDP包回送给发送者,让发送者可以计算和显示往返时间。如果目标主机不存在或宕机,当TTL减小为0时,路由器将会丢弃pinging UDP数据包。在这种情况下,用户会发现目标主机没有任何响应。用户可以尝试再次ping,或者断定目标主机宕机。 - TCP:一种面向连接的协议,用于发送/接收数据流。TCP也可在IP上运行,但它保证了可靠的数据传输。通常,UDP类似于发送邮件的USPS,而TCP类似于电话连接。
- 端口编号:端口号是分配给应用程序的唯一无符号短整数。要想使用UDP或TCP,应用程序(进程)必须先选择或获取一个端口号。前1024个端口号已被预留。其他端口号可供一般使用。应用程序可以选择一个可用端口号,也可以让操作系统内核分配端口号。
- 应用程序 = (主机IP, 协议, 端口号)
- 网络和主机字节序:计算机可以使用大端字节序,也可以使用小端字节序。在互联网上,数据始终按网络序排列,这是大端。在小端机器上,例如基于Intel x86的PC,htons()、htonl()、ntohs()、ntohl()等库函数,可在主机序和网络序之间转换数据。
- TCP/IP网络中的数据流
实践内容
udp实践
server
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#define SERVER_PORT 9999
#define BUFF_LEN 1024
void handle_udp_msg(int fd)
{
char buf[BUFF_LEN]; //接收缓冲区,1024字节
socklen_t len;
int count;
struct sockaddr_in clent_addr; //clent_addr用于记录发送方的地址信息
while(1)
{
memset(buf, 0, BUFF_LEN);
len = sizeof(clent_addr);
count = recvfrom(fd, buf, BUFF_LEN, 0, (struct sockaddr*)&clent_addr, &len); //recvfrom是拥塞函数,没有数据就一直拥塞
if(count == -1)
{
printf("recieve data fail!\n");
return;
}
printf("client:%s\n",buf); //打印client发过来的信息
memset(buf, 0, BUFF_LEN);
sprintf(buf, "I have recieved %d bytes data!\n", count); //回复client
printf("server:%s\n",buf); //打印自己发送的信息给
sendto(fd, buf, BUFF_LEN, 0, (struct sockaddr*)&clent_addr, len); //发送信息给client,注意使用了clent_addr结构体指针
}
}
/*
server:
socket-->bind-->recvfrom-->sendto-->close
*/
int main(int argc, char* argv[])
{
int server_fd, ret;
struct sockaddr_in ser_addr;
server_fd = socket(AF_INET, SOCK_DGRAM, 0); //AF_INET:IPV4;SOCK_DGRAM:UDP
if(server_fd < 0)
{
printf("create socket fail!\n");
return -1;
}
memset(&ser_addr, 0, sizeof(ser_addr));
ser_addr.sin_family = AF_INET;
ser_addr.sin_addr.s_addr = htonl(INADDR_ANY); //IP地址,需要进行网络序转换,INADDR_ANY:本地地址
ser_addr.sin_port = htons(SERVER_PORT); //端口号,需要网络序转换
ret = bind(server_fd, (struct sockaddr*)&ser_addr, sizeof(ser_addr));
if(ret < 0)
{
printf("socket bind fail!\n");
return -1;
}
handle_udp_msg(server_fd); //处理接收到的数据
close(server_fd);
return 0;
}
client
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define SERVER_PORT 9999
#define BUFF_LEN 512
#define SERVER_IP "127.0.0.1"
void udp_msg_sender(int fd, struct sockaddr* dst)
{
socklen_t len;
struct sockaddr_in src;
while(1)
{
char buf[BUFF_LEN] = "TEST UDP MSG!\n";
len = sizeof(*dst);
printf("client:%s\n",buf); //打印自己发送的信息
sendto(fd, buf, BUFF_LEN, 0, dst, len);
memset(buf, 0, BUFF_LEN);
recvfrom(fd, buf, BUFF_LEN, 0, (struct sockaddr*)&src, &len); //接收来自server的信息
printf("server:%s\n",buf);
sleep(1); //一秒发送一次消息
}
}
/*
client:
socket-->sendto-->revcfrom-->close
*/
int main(int argc, char* argv[])
{
int client_fd;
struct sockaddr_in ser_addr;
client_fd = socket(AF_INET, SOCK_DGRAM, 0);
if(client_fd < 0)
{
printf("create socket fail!\n");
return -1;
}
memset(&ser_addr, 0, sizeof(ser_addr));
ser_addr.sin_family = AF_INET;
//ser_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
ser_addr.sin_addr.s_addr = htonl(INADDR_ANY); //注意网络序转换
ser_addr.sin_port = htons(SERVER_PORT); //注意网络序转换
udp_msg_sender(client_fd, (struct sockaddr*)&ser_addr);
close(client_fd);
return 0;
}
《Unix/Linux系统编程》第十一周学习笔记的更多相关文章
- 《Linux内核分析》第一周学习笔记
<Linux内核分析>第一周学习笔记 计算机是如何工作的 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/c ...
- 《Linux内核分析》第二周学习笔记
<Linux内核分析>第二周学习笔记 操作系统是如何工作的 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/ ...
- linux内核分析第五周学习笔记
linux内核分析第五周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...
- Linux内核分析第三周学习笔记
linux内核分析第三周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...
- Linux内核分析第六周学习笔记——分析Linux内核创建一个新进程的过程
Linux内核分析第六周学习笔记--分析Linux内核创建一个新进程的过程 zl + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/U ...
- Linux 内核分析第八周学习笔记
Linux 内核分析第八周学习笔记 zl + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-10 ...
- Linux内核分析第七周学习笔记——Linux内核如何装载和启动一个可执行程序
Linux内核分析第七周学习笔记--Linux内核如何装载和启动一个可执行程序 zl + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study. ...
- linux内核分析第六周学习笔记
LINUX内核分析第六周学习总结 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.c ...
- 20179223《Linux内核原理与分析》第十一周学习笔记
缓冲区溢出漏洞实验 一.实验简介 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况.这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段.这一漏洞的出现是由于数据缓冲器和 ...
- 20135320赵瀚青LINUX内核分析第三周学习笔记
赵瀚青原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 概述 本周是学习的主要是构造 ...
随机推荐
- vim中的命令行 %! 是啥意思?
:%! command pipes the current file's contents to command's stdin, and replaces the file's contents w ...
- Word09 会计电算化节节高升office真题
1.课程的讲解之前,先来对题目进行分析,首先需要在考生文件夹下,将Wrod素材.docx文件另存为Word.docx,后续操作均基于此文件,否则不得分. 2.这一步非常的简单,打开下载素材文件,在[文 ...
- 循环2-if与case语法
一.if语法结构 1. 单分支结构 if < 条件表达式 > then 指令 fi 或者 if < 条件表达式 >:then 指令 fi 2. 双分支结构 if < 条件 ...
- elasticsearch+moloch
1.下载elasticsearch-6.8.7 https://www.elastic.co/cn/downloads/elasticsearch 2.下载moloch-2.2.2-1.x86_64 ...
- docker 搭建mysql主从复制环境(一主两从)
一主多从配置 服务器规划:使用docker方式创建,主从服务器IP一致,端口号不一致 主服务器:容器名docker-mysql-master,端口3306 从服务器:容器名docker-mysql-s ...
- 笛卡尔树 Cartesian tree
给个板子题 笛卡尔树是这样的一种数据结构:对于 \(n\) 个二元组 \((key, value)\) 形成的笛卡尔树,满足如下性质 其 \(key\) 值满足二叉搜索树性质 (中序排列单调递增),\ ...
- Delphi中纤程的使用
首先我们来看看纤程的定义 纤程(来自百科): 纤程是Windows为了将Unix服务程序更好的移植到Windows上而创建的, 线程是在Windows内核中实现的,纤程是在用户模式下实现的,内核对纤程 ...
- ULR1 B. 【ULR #1】光伏元件
一个n∗nn∗n的0101矩阵ai,jai,j,有些位置可以修改,代价为ci,jci,j.要求进行一些修改之后满足:设clicli为第ii行的11的个数,cricri为第ii列的11的个数,要求cli ...
- 法拉第未来任命新CFO!贾跃亭激动发声
近段时间以来,贾跃亭旗下的的法拉第未来(Faraday Future,简称 FF)可谓是动作频频. 一天前,有媒体报道称,FF 任命 Zvi Glasman 为其首席财务官.其将负责公司财务.投资者关 ...
- DAST精简代码
先训练G:先不计算D的梯度: 判别器输入类型为(源域,0)或者(目标域,1),输出图片为真实图片(源域)的概率值for param in model_D.parameters(): # model_D ...