Linux下的socket编程实践(一) 网络基本知识以及 TCP/IP简述

ISO/OSI七层参考模型

1.物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后再转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。(标志:RJ-45)

2.数据链路层:定义了如何让格式化数据以进行传输,以及如何让控制对物理介质的访问。这一层通常还提供错误检测和纠正,以确保数据的可靠传输,交换机属于本层。

3.网络层:在位于不同地理位置的网络中的两个主机系统之间提供连接和路径选择。Internet的发展使得从世界各站点访问信息的用户数大大增加,而网络层正是管理这种连接的层。(标志:路由选择,IP/OSPF,ICMP,IGMP)

4.传输层:定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。 主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这一层数据叫做段。

5.会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)。

6.表示层:可确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取。例如,PC程序与另一台计算机进行通信,其中一台计算机使用扩展二一十进制交换吗(EBCDIC),而另一台则使用美国信息交换标准码(ASCII)来表示相同的字符。如有必要,表示层会通过使用一种通格式来实现多种数据格式之间的转换。

7.应用层:是最靠近用户的OSI层。这一层为用户的应用程序(例如电子邮件、文件传输和终端仿真)提供网络服务。

(标志:HTTP,HTTPS,FTP,TELNET,SSH,SMTP,POP3)

TCP/IP四层模型

ISO制定的OSI参考模型的过于庞大、复杂招致了许多批评。与此对照,由技术人员自己开发的TCP/IP协议栈获得了更为广泛的应用。

应用层: FTP,TELNET为了完成一定的用户需求,自定义协议,QQ协议

传输层:TCP UDP

网络层: ICMP,IP,IGMP

数据链路层: ARP,RARP硬件接口

运行FTP协议的两台主机:

每个层次具有自己的协议,每层之间进行通信;他们的语言一致,我们可以看作是A进程和B进程之间进行对等通信,也就是虚电路(并不是真正的建立连接线)对等数据传输的是逻辑流,例如现在有两个人通过手机进行通信,好像就在耳边,其实是通过电磁波。

封装:

分用

端口:

端口由IANA分配和控制他们紧密绑定一些服务:0~1023

注册端口:1024~49151,在这之间端口松散的绑定一些服务

动态或者私有(临时)端口 49152~65535(实际上从1024)开始分配

链路层:

以太网的帧格式

链路层的数据包,称为以太网帧; 链路层不识别IP地址[因为IP地址是逻辑地址],链路层识别物理网卡MAC地址[硬件地址]; 需要根据IP地址(逻辑地址)找到对方的MAC地址(ARP地址解析协议)[MAC —> IP地址方向地址解析];MAC->IP 反向地址解析(RARP协议); 类型(2字节)用来区分IP,ARP,RARP。

//以太网首部代码
struct ethernet_hdr
{
    char dest_mac[6];
    char src_mac[6];
    short protocol;
};  

MTU/路径MTU

链路层具有最大传输单元MTU这个特性,它限制了数据帧的最大长度,不同的网络类型都有一个上限值。以太网的MTU是1500,你可以用 netstat -i 命令查看这个值。如果IP层有数据包要传,而且数据包的长度超过了MTU,那么IP层就要对数据包进行分片(fragmentation)操作,使每一片的长度都小于或等于MTU。另外,多个网络的链路层可能有不同的MTU,选择通信路径中较小的MTU,称作路径MTU;但是分片会降低网络的通信效率,应该尽量避免。

ARP地址解析协议

本地ARP高速缓存

//ARP首部代码
struct arp_hdr
{
    unsigned short hwtype;  // 固定1
    unsigned short protype; // 固定0x0800(代表为IP协议做请求)
    unsigned char hwaddrlen;    // 固定6(即MAC地址长度)
    unsigned char proaddrlen;   // 固定4 (即IP地址长度)
    unsigned short opcode;  // Request - 1, Reply - 0x0002
    unsigned char sender_mac[6];    // 发送者MAC
    unsigned char sender_ip[4]; // 发送者IP
    unsigned char dest_mac[6];  // 接收者MAC
    unsigned char dest_ip[4];   // 接收者IP
};  

源端和目的端都将加入ARP缓冲区。

RARP反向地址解析协议,适用于无盘工作站,IP一般存于配置文件中

这个时候要想获取IP地址,就通过RARP协议,通过向RARP服务器发送请求

网络层:

IP数据报

首部最大长度是15*4=60个字节,15最为单位,选项最多有40个字节。

协议类型8位 判断高层是TCP还是UDP,头部校验和校验IP头部的完整性,并不校验数据的完整性。

服务类型:

IP数据报最大可达65535;分片共享一个标识号

网际校验和算法:  http://blog.csdn.net/zhq651/article/details/8515575

//IP首部代码
struct ip_hdr
{
    char  ver_hl;
    char  tos;
    unsigned short len;
    unsigned short id;
    unsigned short fragment;
    char ttl;
    char protocol;
    unsigned short hdr_chksum;
    char src_ip [4];
    char dest_ip [4];
};  

路由过程:

顺序:搜索匹配的主机地址

搜索网络地址

搜索默认表项

ICMP协议

ICMP协议用于传递差错信息、时间、回显、网络信息等控制数据,工作于网络层(IP),Ping程序使用ICMP协议实现。

//ICMP首部代码
struct icmp_hdr
{
    char    type;           // ICMP报文类型
    char    code;           // “子类型”
    unsigned short  icmpchksum; // 校验和
};  

UDP报文格式

//UDP首部代码
struct udp_hdr
{
    unsigned short src_port;
    unsigned short dest_port;
    unsigned short len;
    unsigned short chksum;
}; 

TCP报文头部:

连接建立三次握手

连接终止四次挥手

注:慢启动中的慢 是指基数比较小。

步骤a:应用程序ping会判断发送的是主机名还是IP地址,调用函数gethostbyname()解析主机机B,将主机名转换成一个32位的IP地址。这个过程叫做DNS域名解析.

步骤b:ping程序向目的IP地址发送一个ICMP的ECHO包

步骤c:将目标主机的IP地址转换为48位硬件地址,在局域网内发送ARP请求广播,查找主机B的硬件地址。

步骤d:主机B的ARP协议层接收到主机A的ARP请求后,将本机的硬件地址填充到应答包,发送ARP应答到主机A。

步骤e:发送ICMP数据包到主机B

步骤f:主机B接收到主机A的ICMP包,发送响应包。

步骤g:主机A接收到主机B的ICMP包响应包。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-06 11:26:38

Linux下的socket编程实践(一) 网络基本知识以及 TCP/IP简述的相关文章

Linux下的socket编程实践(十) 基本UDP编程细节

在我的这两篇博客中,简单介绍并实现了基于UDP(TCP)的windows(UNIX下流程基本一致)下的服务端和客户端的程序,本文继续探讨关于UDP编程的一些细节. http://blog.csdn.net/nk_test/article/details/47733307 http://blog.csdn.net/nk_test/article/details/47756381 下图是一个简单的UDP客户/服务器模型: 我在这里也实现了一个简单的UDP回射服务器/客户端: /**实践: 实现一个基

Linux下的socket编程实践(四)TCP服务端优化和常见函数

并发下的僵尸进程处理 只有一个进程连接的时候,我们可以使用以下两种方法处理僵尸进程: 1)通过忽略SIGCHLD信号,避免僵尸进程 在server端代码中添加 signal(SIGCHLD, SIG_IGN); 2)通过wait/waitpid方法,解决僵尸进程 signal(SIGCHLD,onSignalCatch); void onSignalCatch(int signalNumber) { wait(NULL); } 那么如果是多进程状态下多个客户端同时关闭呢? 我们可以用下面的客户端

Linux下的socket编程实践(三)端口复用和 P2P多进程服务器

Socket端口复用 先说为什么要使用socket端口复用?如果你遇到过这样的问题:server程序重启之后,无法连接,需要过一段时间才能连接上? 1.一个监听(listen)server已经启动 2.当有client有连接请求的时候,server产生一个子进程去处理该client的事物. 3.server主进程终止了,但是子进程还在占用该连接处理client的事情.虽然子进程终止了,但是由于子进程没有终止,该socket的引用计数不会为0,所以该socket不会被关闭. 4.server程序重

Linux下的socket编程实践(四)TCP的粘包问题和常用解决方案

TCP粘包问题的产生 由于TCP协议是基于字节流并且无边界的传输协议, 因此很有可能产生粘包问题.此外,发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一个TCP段.若连续几次需要send的数据都很少,通常TCP会根据优化算法把这些数据合成一个TCP段后一次发送出去,但是接收方并不知道要一次接收多少字节的数据,这样接收方就收到了粘包数据.具体可以见下图: 假设主机A send了两条消息M1和M2 各10k 给主机B,由于主机B一次提取的字节数

Linux下的socket编程实践(八) Select的限制和poll(并发的初步知识)

select的限制 用select实现的并发服务器,能达到的并发数一般受两方面限制: 1)一个进程能打开的最大文件描述符限制.这可以通过调整内核参数来改变.可以通过ulimit -n(number)来调整或者使用setrlimit函数设置(需要root权限),但一个系统所能打开的最大数也是有限的,跟内存大小有关,可以通过cat /proc/sys/fs/file-max 查看. 2)select中的fd_set集合容量的限制(FD_SETSIZE,一般为1024),这需要重新编译内核才能改变.

Linux下的socket编程

网络通信编程即编写通过计算机与其他程序之间进行通讯的程序,相互通信的程序中一方可以称为客户端程序,另一方称为服务程序,应用系统提供Socket编程接口可以编写自己的网络程序. 一  通过TCP/IP协议进行传输 TCP:为应用程序提供可靠的通信连接.适合一次传输大批的数据情况.并使用于要求得到的响应程序. UDP:提供无线连接通信,且对传送包进行可靠性保证.适合一次传输少量的数据,可靠性则由应用层来负责. 二  Socket套接字 网络通信编程通过socket接口来进行的.socket接口是TC

网络编程学习笔记:linux下的socket编程

socket是进程通信的一种方式,通过调用一些API可以实现进程间通信,建立连接以及收发信息的过程如下图所示: 这些函数的用法如下: 1.int socket(int protocolFamily, int type, int protocol); 返回描述符sockfd l  protocolFamily:协议族,AF_INET(IPV4).AF_INET6(IPV6).AF_LOCAL(或称AF_UNIX,unix域socket).AF_ROUTE等.协议族决定了socket的地址类型,在通

LINUX 下 ipv6 socket 编程

大家都知道,随着互联网上主机数量的增多,现有的32位IP地址已经不够用了,所以推出了下一代IP地址IPv6,写网络程序的要稍微改变一下现有的网络程序适应IPv6网络是相当容易的事.对于我们来说就是IP地址变化了,所以程序里在用到IP地址的地方做相应的改变就可以了. 记住:主要是改变程序里设置IP地址和端口等部分的代码. 服务器端源代码如下:/***********************/#include <stdio.h>#include <stdlib.h>#include &

Linux下C++的编程——开发环境搭建与第一个程序

上一篇文章Linux下C++的编程--开偏介绍中我们已经介绍了GUN.GCC.G++等一些重要的概念,现在应该开始动手实践了! 开发工具的安装 环境 Distributions版本:CentOS 6.7 Linux内核片:2.6.32-573.3.1.el6.i686 一般Linux安装完之后默认就已经安装了GCC(GNU Compiler Collection),你可以查看一下gcc和g++的版本号检查gcc和g++是否已经安装. [luowf@luoweifu ~]$ gcc -v gcc