(一)基本概念,socket,tcp

网络编程
网络目的 : 数据的传输
网络数据传输是一个复杂的过程
ISO: 国际标准化组织
OSI 七层模型  -->> 网络通信标准化流程

应用层 : 提供用户服务,具体内容由特点程序规定
表示层 : 数据的压缩优化
会话层 : 建立应用连接,选择传输层服务
传输层 : 提供不同的传输服务,流量控制
网络层 : 路由选择,网络互连
链路层 : 提供链路交换,具体消息以帧发送
物理层 : 物理硬件,接口,网卡,线路

osi七层模型优点: 将功能分开,降低了网络传输中的耦合性,每一部分完成自己的功能,
                           可以在开发和实施的过程中各司其职。

cookie
高内聚: 单个模块功能尽量单一
低耦合: 模块之间尽量减少关联和影响

四层
应用层 : 应用层 表示层 会话层
传输层 : 传输层
网络层 : 网络层
物理链路层 :链路层和物理层

五层(tcp/ip模型)
应用层 : 应用层 表示层 会话层
传输层 :传输层
网络层 :网络层
链路层 :链路层
物理层 :物理层

协议(网络协议) :在网络通信中,各方必须遵守的规定,包括建立什么样的连接,消息结构等  

应用层:TFTP  HTTP  DNS  SMTP
传输层:TCP  UDP
网络层:IP
物理层:IEEE

网络基本概念
主机: "localhost" 表示本台计算机

网络上: 只在本地测试使用
            'localhost' '127.0.0.1'
           如果想在网络上进行测试
             '0.0.0.0'  ''  '本机IP'

cookie
查看IP网络信息
linux     ifconfig
win       ipconfig

获取计算机名称

#先导入socket模块 
In [2]: socket.gethostname() 
#Out[2]: 'tedu'

获取主机IP
In [5]: socket.gethostbyname('localhost')
Out[5]: '127.0.0.1'
In [6]: socket.gethostbyname('tedu')
Out[6]: '127.0.1.1'
In [7]: socket.gethostbyname('')

Out[7]: '0.0.0.0'

IP地址
在网络上用于区分一台计算机
IPv4 : 点分十进制  e.g. 192.168.1.72   0~255       
          32位二进制表示

IPv6 : 128

网络连接测试命令: ping 172.60.50.92

特殊IP
127.0.0.1 本地测试IP  (本地计算机测试用)
0.0.0.0 本地网卡通用IP   (局域网内)
192.168.1.0  表示当前网段  (192.168.1.0 ~ 1
192.168.1.1  表示网关     (类似路由器)
192.168.1.255  广播地址  

获取服务主机信息
In [7]: socket.gethostbyaddr("www.baidu.com")
Out[7]: ('127.0.0.1', [],   ['119.75.213.61'])
          主机        别名   IP地址

将ip十进制转化为二进制
In [12]: socket.inet_aton("192.168.1.2")
Out[12]: b'\xc0\xa8\x01\x02'

将ip二进制转化为十进制
In [11]: socket.inet_ntoa(b"\xc0\xa8\x01\x02")
Out[11]: '192.168.1.2'

域名 : 网络服务器IP地址的名称
url : 在网络上定位某个资源位置的字串(网址如www.baidu.com

端口号 : 端口号是网络地址的一部分,在一个系统中,每个网络应用都会有一个唯一的端口号,取来区别其他应用,接受发往这个端口的消息

数字范围 : 1 ~ 65535
1 ~ 255 : 一些众所周知的端口
256 ~ 1023 : 系统应用
1024 ~ 65535 : 自用
推荐 > 10000

测试一个软件的端口号
In [9]:  socket.getservbyname('mysql')
Out[9]: 3306

传输层服务

面向连接的传输服务 --> tcp协议
传输特征:
    * 提供可靠的传输服务
        可靠性表现: 数据在传输过程中,无失序,无差错,无重复,无丢失

    * 传输过程中有建立和断开连接的过程

       三次握手: 建立数据传输两端的持续连接
            1.客户端向服务器发起连接请求
            2.服务器收到连接请求进行确认,返回报文
            3.客户端收到服务器确认进行连接创建

       四次挥手: 断开连接的两端,保证数据的传输完整
            1.主动方发送报文,告知被动方要断开连接
            2.被动方返回报文,告知收到请求,准备断开
            3.被动方再次发送报文,告知准备完毕可以断开

            4.主动方发送报文完成断开

    适用情况:  文件的上传下载,网络情况良好,需要必须保证可靠性的情况
    比如: 信息聊天,文件上传下载,邮件,网页获取

面向无连接的传输服务 --> udp协议
    传输特征 :
    * 不保证传输的可靠性
    * 无需建立三次握手和四次挥手的连接断开过程
    * 消息的收发比较自由,不受其他约束

    适用情况:网络情况较差,对可靠性要求不高,收发消息的两端不适合建立固定连接
    比如: 网络视频,群聊,发送广播

问题总结:
1.osi模型
2.三次握手和四次挥手
3.tcp和udp的区别

socket套接字编程
    目的:通过编程语言提供的函数接口进行组合,更简单的完成基于tcp和udp通信的网络编程

    套接字:完成上述目标的编程方法方案

    套接字的分类
    流式套接字(SOCK_STREAM):传输层基于tcp的协议进行通信
    数据报套接字(SOCK_DGRAM):传输层基于udp的协议进行通信
    底层套接字(SOCK_RAM):访问底层协议的套接字

TCP套接字
import socket
1.创建套接字
    socket.socket(socket_family = AF_INET, socket_type = SOCK_STREAM,  proto = 0)
    功能: 创建一个套接字
    参数:  socket_family  选择地址族类型  AF_INET 表示IPV4
              socket_type   选择套接字类型  SOCK_STREAM 流式   SOCK_DGRAM 数据报
              proto       通常为0 (表示选择子协议)
    返回值: 返回一个套接字对象

2.绑定IP端口
sockfd.bind()
功能:绑定IP和端口
参数:二元元组,第一项为ip 第二项为端口号
             e.g. ("192.168.1.2",8888)

3.将套接字设置为可监听
sockfd.listen(n)
功能:将套接字设置为监听套接字,并设置监听队列
参数:监听对象的大小  n为大于0的正整数

4.等待客户端的连接
connfd,addr = sockfd.accept()
功能:阻塞等待客户端的连接
返回值: connfd 一个新的套接字,用于和指定客户端通信
            addr 连接的客户端的地址

*阻塞函数:程序运行到阻塞函数位置,如果某种预期条件没有达成则暂停运行,直到条件达成后再继续运行

5.消息收发
data = connfd.recv(buffersize)
功能:接收消息
参数:每次最多接受的消息大小 bytes
返回值:返回接收到的内容   decode()

n = connfd.send(data)
功能:发送消息
参数:要发送的内容  必须是bytes格式 encode()
返回值:实际发送的字节数 

6.关闭套接字
closs()

功能:关闭套接字,tcp连接断开

* telnet ip port 表示连接tcp服务端 

tcp客户端
1.创建套接字
socket()
* 通信的两端套接字类型相同

2.发起连接
connect()
功能: 发起连接请求
参数: 元组,服务器端的地址

3.发收消息
send recv
* 两端收发需要配合

4.关闭套接字
close()

作业:
1.口述三个问题
2.将tcp服务端和客户端改成可以循环收发的模式,当发送##时两端都退出
3.当客户端退出后,服务端可以继续等待连接其他客户端,进行操作
 

#tcp_server.py
from socket import *
sockfd = socket(AF_INET,SOCK_STREAM) #创建tcp套接字
sockfd.bind(("127.0.0.1",8883)) #绑定IP和端口
sockfd.listen(5) #设置监听
print("Waiting for connect....")  #等待客户端链接
connfd,addr = sockfd.accept()
print("Connect from",addr)
#接收
while True:
    data = connfd.recv(1024)
    # print(repr(data))
    if not data :
        break  
    print("Receive message >>",data.decode())
    #发送
    n = connfd.send(b"Receive your message\n")
    print("Send %d bytes data"%n)
#关闭套接字
connfd.close()
sockfd.close()

from socket import * 
sockfd = socket()  #创建套接字 tcp 默认参数即可 
sockfd.connect(('127.0.0.1',8883)) #发起链接请求
while True:
    data = input("发送>>")
    if data == "##":
        break
    sockfd.send(data.encode()) #发送消息 bytes格式
    data = sockfd.recv(1024).decode()
    print(data)
#关闭套接字
sockfd.close()

猜你喜欢

转载自blog.csdn.net/zh__quan/article/details/81044658