计算机网络通讯

前言:
本博客的大部分例子都是python2实现的

一、计算机通信

通信方式

通信方式有三种:单工、半双工、全双工

1.单工

单工就是数据只能单向传输的通信方式,比如打印机就是单工通信的设备,打印机是接收器,计算机是发送器,数据只能由发送器向接收器发送。

2.半双工

半双工通信当中,A可以向B发送数据,B也可以向A发送数据,但是在同一时间内只能有一方向另一方发送数据。

3.全双工

在同一个时间点,A可以向B方法数据,B也可以向A发送数据。电话就是全双工的。

参照资料:樊昌信《通信原理》第一章

通信协议

二、计算机网络

互联网

顾名思义,互联网就是多个计算机网络连接起来的整体。

下面,我将会按照自己的理解,从概念上介绍“互联网”的含义

1.网络

对于网络的定义,百度是这样说的:网络是由节点和连线构成,表示诸多对象及其相互联系,在数学上,网络是一种图的数据结构。

实际情况中,哪怕只是两个结点连接起来的整体也是网络,那是最简单的网络。

这里写图片描述

2.计算机网络

根据数学上网络的定义,计算机科学中的网络是两个或者多个计算机结点组成的整体。

这里的计算机概念很模糊,可以是PC、手机、和任何可以进行通信的设备。甚至说,如果我家的狗狗如果能给你的电脑发送信息,那么它也算是计算机。

3.互联网

多个局域网相互连接起来的网络就是互联网,不管各个网络内部的结点个数、通讯协议、传输媒介是如何的,都不影响其作为一个计算机网络的本质,因此,互联网中的每个网络可以是各种各样的 。

这里写图片描述

实际上,在上述的互联网中,各个将计算机网络实际上就是互联网中的节点,而节点内部的特性是被屏蔽了。

正因为这样,决定了网络节点A内部的节点和网络节点B内部的节点要通信是困难的。

计算机网络分类

1.按覆盖范围分类
2.按传输媒介分类
3.拓扑结构分类
4.使用目的分类
5.按网络协议分类

以太网 、令牌环网等

三、计算机通信实现

计算机之间如何通信?

前面我介绍了计算机网络的一些特点,那么我们来看一个最基本的问题:计算机之间如何通信?

是的,不管一个计算机网络内部采用怎样的连接方式(拓扑结构),一个最基本的前提是,计算机要怎样才能相互通信呢?

有两个问题要解决:

  • 信息到达目标计算机节点

  • 目标计算机节点收到的信息是完整,没被次修改过的

经过前人多年的探索,抽象出OSI七层模型TCP/IP四层协议

1、数据链路层

经过探索,人们解决了两个计算机节点如何通信的难题!,让两台将计算机之间可以传输数据,保持数据的完整性能。其中,数据链路层最杰出的是实现者就是以太网。

以太网具有以下特点:

  • 使用分组交换技术,将一个大的数据包切割成一定的大小再发送,并且在接收端拼接起来

  • 使用CSMA/CD(载波监听多路访问及冲突检测)技术技术检查线路情况。

2、网络层

交换机和路由器根据路由表中MAC地址和接口的对应关系,在同一个网络中,可以将信息发送给对方。

但是,我们需要多个网络进行互联,那就必须要有一种安全的方案,使得我们某个网络内部的计算机可以联系上级的计算机。

因此,就采用IP,给每个计算机分配一个IP,并且在一个网络中存在一个连接外部网络的接口,那就是网关,通常就是我们的路由器,因此,路由器就有了多个职责:

  • 将数据包发送给同一网络的计算机
  • 如果目标主机不是本网络的,就发送给外部网络,也就是wlan口指定的网关。

为了防止目标地址即存在本局域网中,有出现在wlan接口的网络中,路由器的wlan和vlan接口IP不可以是通过一个网段。
同样的道理,公网IP是不可能出现在局域网中的,这也就是你在百度上输入一个IP地址,只要是局域网地址,哪怕你的网络中不存在这个IP地址所属的网络,都知道是局域网地址,因为这个国际规定的。

IP地址有A、B、C、D、E 共5类,其中D、E是保留地址,不可以分配使用,其他的3类部分是公网IP,部分是局域网IP:

  1. A类地址
    ⑴ A类地址第1字节为网络地址,其它3个字节为主机地址。
    ⑵ A类地址范围:1.0.0.1—126.155.255.254
    ⑶ A类地址中的私有地址和保留地址:
    ① 10.X.X.X是私有地址(所谓的私有地址就是在互联网上不使用,而被用在局域网络中的地址)。
    ② 127.X.X.X是保留地址,用做循环测试用的。

  2. B类地址
    ⑴ B类地址第1字节和第2字节为网络地址,其它2个字节为主机地址。
    ⑵ B类地址范围:128.0.0.1—191.255.255.254。
    ⑶ B类地址的私有地址和保留地址
    ① 172.16.0.0—172.31.255.255是私有地址
    ② 169.254.X.X是保留地址。如果你的IP地址是自动获取IP地址,而你在网络上又没有找到可用的DHCP服务器。就会得到其中一个IP。

  3. C类地址
    ⑴ C类地址第1字节、第2字节和第3个字节为网络地址,第4个个字节为主机地址。另外第1个字节的前三位固定为110。
    ⑵ C类地址范围:192.0.0.1—223.255.255.254。
    ⑶ C类地址中的私有地址:
    192.168.X.X是私有地址。

  4. D类地址
    ⑴ D类地址不分网络地址和主机地址,它的第1个字节的前四位固定为1110。
    ⑵ D类地址范围:224.0.0.1—239.255.255.254

  5. E类地址
    ⑴ E类地址也不分网络地址和主机地址,它的第1个字节的前五位固定为11110。
    ⑵ E类地址范围:240.0.0.1—255.255.255.254

转载自 A、B、C、D和E类IP地址

四、网络编程接口——socket

*Unix系统提供的socket系列接口让开发者可以封装发送TCP/IP各层的数据包,我们常见的就是TCP、UDP,实际上不仅如此,还可以封装IP包、数据帧。

看这张图:

这里写图片描述

其中 SOCK_STREAM (TCP)、SOCK_DGRAM (UDP) 工作在传输层,SOCK_RAW 工作在网络层。
SOCK_RAW 可以处理ICMP、IGMP等网络报文、特殊的IPv4报文、可以通过IP_HDRINCL套接字选项由用户构造IP头。

参考:SOCK_RAW 与 SOCK_STREAM 、SOCK_DGRAM 的区别
C接口如下:

#发送接收ip数据包
socket(AF_INET, SOCK_RAW,IPPROTO_TCP|IPPROTO_UDP|IPPROTO_ICMP) 

#发送接收以太网数据帧
socket(PF_PACKET, SOCK_RAW,htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))

例子
理解一下SOCK_RAW的原理, 比如网卡收到了一个 14+20+8+100+4 的udp的以太网数据帧.

首 先,网卡对该数据帧进行硬过滤(根据网卡的模式不同会有不同的动作,如果设置了promisc混杂模式的话,则不做任何过滤直接交给下一层输 入例程,否则非本机mac或者广播mac会被直接丢弃).

这里是原始套接字:

按照上面的例子,如果成功的话,会进入ip输入例程.但是在进入ip输入例程之前,系统会检查系 统中是否有通过socket(AF_PACKET, SOCK_RAW, ..)创建的套接字.如果有的话并且协议相符,在这个例子中就是需要ETH_P_IP或者ETH_P_ALL类型.系统就给每个这样的socket接收缓 冲区发送一个数据帧拷贝.然后进入下一步.

其次,进入了ip输入例程(ip层会对该数据包进行软过滤,就是检查校验或者丢弃非本机ip 或者广播ip的数据包等,具体要参考源代码),例子 中就是如果成功的话会进入udp输入例程.但是在交给udp输入例程之前,系统会检查系统中是否有通过socket(AF_INET, SOCK_RAW, ..)创建的套接字.如果有的话并且协议相符,在这个例子中就是需要IPPROTO_UDP类型.系统就给每个这样的socket接收缓冲区发送一个数据 帧拷贝.然后进入下一步.

最后,进入udp输入例程 …

注意:
如果校验和出错的话,内核会直接丢弃该数据包的.而不会拷贝给sock_raw的套接字,因为校验和都出错了,数据肯定有问题的包括所有信息都没有意义了.

来源:linux sock_raw原始套接字编程

1、网卡、IP和端口

每个计算机可以有多个网卡,每张网卡只能设置一个IP,并且每个计算机都有一个回环网卡,IP是127.0.0.1

每个网卡/IP都有多个端口,0~65535,其中,1024以内的端口号默认给系统使用,所以,我们自己写服务器的时候,就不要使用1024以内的了,除非是http、ftp、ssh等常见服务。

2、收发信息

socket是操作系统提供的网络通信接口,我们可以利用socket发送和接受计算机收到的信息。

服务器进程需要指定绑定的IP和端口,以在接收到信息的时候做出响应,如果想绑定所有IP,就设置为0.0.0.0,如果端口号是0,系统会随机分配端口号

例子:只绑定127.0.0.1

#!/usr/bin/env python
#-*- coding:utf8 -*-

import  socket
import threading

bind_ip = "127.0.0.1"     #绑定ip 127.0.0.1
bind_port = 9999

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server.bind((bind_ip, bind_port))
# 最大连接数为5
server.listen(5)

上述中只绑定了127.0.0.1:9999,因此,客户端访问本服务器的其他IP:9999的时候,进程是不会接受到的,IP+端口是一个组合,具有唯一性,120.0.01:9999和192.168.1.2:9999是不一样的

注意:
绑定的IP一定要是服务端所在计算机的IP之一,例如,服务器根本没有任何一张网卡的IP是10.2.1.3,你却要绑定到10.2.1.3:9999,会绑定失败,你不可以通过绑定百度服务器的IP来窃取它的数据

指定IP+端口不可以重复绑定

例子:绑定所有网卡上的9999端口

tcp服务器代码:

#!/usr/bin/env python
#-*- coding:utf8 -*-

import  socket
import threading

bind_ip = "0.0.0.0"     #绑定ip:这里代表任何ip地址
bind_port = 9999

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server.bind((bind_ip, bind_port))
# 最大连接数为5
server.listen(5)

print "[*] Listening on %s:%d" % (bind_ip, bind_port)

# 这是客户处理进程
def handle_client(client_socket):
    #打印出客户端发送得到的内容
    request = client_socket.recv(1024)

    print "[*] Received: %s" % request

    #发送一个数据包
    client_socket.send("ACK!")
    client_socket.close()


while True:
    client,addr = server.accept()

    print "[*] Accepted connection from: %s:%d" % (addr[0], addr[1])

    #挂起客户端线程,处理传人的数据
    client_handler = threading.Thread(target=handle_client, args=(client,))
    client_handler.start()

客户端连接代码:

#!/usr/bin/env python
#-*- coding:utf8 -*-

import socket

target_host = "127.0.0.1"
target_port = 9999

#建立一个socket对象(AF_INET:使用标准IPV4地址和主机名,  SOCK_STREAM:TCP客户端)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接客户端
client.connect((target_host,target_port))

# 发送一些数据(这是一个HTTP请求)
str = """
GET / HTTP/1.1
Host:127.0.0.1


"""
client.send(str)

# 接收一些数据(4096个字符)
response = client.recv(4096)

print response

五、即时通讯软件

即时通讯(Instant Messaging),简称IM,允许两人或多人使用网络实时的传递文字消息、文件、语音与视频交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值