ttp://www.cnblogs.com/Eva-J/articles/8066842.html
一些概念
不同机器上的程序之间通信
所有的网络通信都基于客户端与服务端
服务端:要一直运行,等待服务别人
客户端:客户用的时候才使用的服务
想要实现通信:
网卡和网线
网卡上有全球唯一的mac地址 由12位16进制数表示 前六位是厂商编号,后六位是流水线号
ip地址:0.0.0.0 - 255.255.255.255 十进制 八进制中网络部分是前24位,主机部分是后8位
127.0.0.1是自己的回环地址
现在最广泛的最主要还是IPv4,v6又增加了两个字节
ip地址通过arp协议就能找到对应的mac地址
交换机的出现解决了多台机器的通信问题
arp协议:
广域网与路由器
网关
局域网中的机器想要访问局域网外的机器需要通过网关访问
IP地址 与 子网掩码 按位与
比如我的IP地址:10.41.157.29 二进制:00001010.00101001.10011101.00011101
子网掩码:255.255.0.0 二进制:11111111.11111111.00000000.00000000
按位进行与运算 :00001010.00101001.00000000.00000000 这是局域网的网段地址 10.41.0.0 前三字节是局域网的网段,最后一个字节可变
通过网络找到机器后,怎么能找到要通信的程序呢?
端口 port
在计算机上,每个需要网络通信的程序,都会开一个端口。同一时间只会有一个程序占用一个端口,不可能在同一时间有两个端口占用
端口范围:0-65535 一般情况下 开8000之后的端口
ip+端口 就可以在茫茫的网络中,找到唯一的机器上的唯一上的程序
TCP协议和UDP协议
当应用程序希望通过 TCP 与另一个应用程序通信时,它会发送一个通信请求。这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP 将在两个应用程序之间建立一个全双工 (full-duplex) 的通信。全双工:双方都可以收发信息
这个全双工的通信将占用两个计算机之间的通信线路,直到它被一方或双方关闭为止。
建立链接:三次握手 一般都是客户端发起
断链:四次挥手
只要连上了,就会一直占用着,知道断开
UDP
不占连接 收没收到不一定
QQ就是基于UDP的协议
TCP可看成打电话,UDP看成发短信 写信
TCP是面向连接的,有比较高的可靠性, 一些要求比较高的服务一般使用这个协议,如FTP、Telnet、SMTP、HTTP、POP3等。 而UDP是面向无连接的,使用这个协议的常见服务有DNS、SNMP、QQ等。对于QQ必须另外说明一下,QQ2003以前是只使用UDP协议的,其服务器使用8000端口,侦听是否有信息传来,客户端使用4000端口,向外发送信息(这也就不难理解在一般的显IP的QQ版本中显示好友的IP地址信息中端口常为4000或其后续端口的原因了),即QQ程序既接受服务又提供服务,在以后的QQ版本中也支持使用TCP协议了。
互联网协议与osi模型
传输过程:
数据链路层跟arp协议打交道的
应用层的协议: http(https)网页协议,ftp文件传输协议,SMTP邮件相关的协议
Socket概念
套接字(Socket)是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
可以看成一个模块
套接字家族
从Socket角度看TCP和UDP协议:
基于TCP协议的socket
server端
import socket sk = socket.socket() # bind中传入一个元组 元组中是ip地址和端口 端口是整数 sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字 sk.listen() #监听链接 等着别人的请求 conn,addr = sk.accept() #接受客户端链接 conn 连接 addr 别人的地址 ret = conn.recv(1024) #接收客户端信息 默认传入1024 print(ret) #打印客户端信息 conn.send(b'hi') #向客户端发送信息 conn.close() #关闭客户端套接字 sk.close() #关闭服务器套接字(可选) 如果不关闭,还能继续接收
client端
import socket sk = socket.socket() # 创建客户套接字 sk.connect(('127.0.0.1',8898)) # 尝试连接服务器 sk.send(b'hello!') ret = sk.recv(1024) # 对话(发送/接收) print(ret) sk.close() # 关闭客户套接字
例子: 聊天
有收必有发,收发必平等。send和recv必相等
客户端:
import socket sk = socket.socket() sk.connect(('127.0.0.1', 8080)) while True: info = input('>>>') sk.send(bytes(info.encode('utf-8'))) ret = sk.recv(1024).decode('utf-8') print(ret) if ret == 'bye': sk.send(b'bye') break sk.close()
注意:
# 以下两者是一样的 bytes('你好', encoding='utf-8') bytes('你好'.encode('utf-8'))
服务端:
import socket sk = socket.socket() sk.bind(('127.0.0.1', 8080)) sk.listen() conn, addr = sk.accept() print(addr) while True: ret = conn.recv(1024).decode('utf-8') if ret == 'bye': break print(ret) info = input('>>>') conn.send(bytes(info, encoding='utf-8')) conn.close() sk.close()