两台机器实现通信的基本原理
概念:网络传输协议有很多,列出常见的,以及socket
协议 | 该协议的场所 |
HTTP | 网站协议 |
SMTP | 邮件协议 |
DNS | 域名解析IP的协议 |
FTP | 上传和下载的协议 |
ssh | 实现电脑远程连接 |
snmp | 网络监控 |
ICMP | ping包的 |
DHCP | IP分配的 |
这些协议不管是什么协议,都是干两个事情,发送数据和接受数据 。
从底层实现发生和接受数据太麻烦了,因而别人将这个抽象成接口,供我们使用,这就是socket,
socket 干什么事?就是实现接收数据和发生数据。
TCP/IP协议
网络传输协议是基于 TCP/IP协议的,这个协议是用来建立两台机器的连接使用的和它一个作用的协议有UDP协议。
三次握手:
OSI7层
应用层 | |
表示层 | |
会话层 | |
传输层 | 大部分协议在传输层,少数例外 |
网络层 | 认识IP地址一般用TCP/IP来建立连接(连接三次握手,四次断开) |
数据链路层 | 只认识mac地址,不认识IP地址 |
物理层 |
使用python的socket编程实现两台电脑之间的通信
可以使用两种方式做演示,一个电脑和两台电脑
工作流程:
服务器端编程:本服务器有一个程序正在运行,另一台机器与这个程序进行通信。
需要知道本服务器的IP地址和这个程序的端口号。
步骤:服务器端:
1,生成服务器对象:传入连接方式ipv4还是ipv6 TCP/IP协议还是UDP
2,绑定监听接口并且进行监听这个窗口是否有人连接。
3,等待消息的到来。
4,接收消息。
5,打印接收的消息
6,将这个消息进行简单处理在发送回去。
客户端:
1,生成客户端对象并建立连接:传入连接方式ipv4还是ipv6 TCP/IP协议还是UDP
2,发送数据
3,接收服务器端的数据
4,打印服务器收到的数据
5,关闭连接
一台电脑:只需要将IP地址改成'localhost'即可
1,使用两台电脑,一个window10系统作为客户端,另一个进行桥接网络的虚拟机Ubuntu系统作为服务器端。
将服务器端代码放到Ubuntu系统上运行。代码如下:先接收客户端信息在发送回去。注意: 所有数据必须用字节流格式才能传输
import socket
server = socket.socket()
server.bind(("192.168.1.105",6969)) #绑定要监听的端口port
server.listen() # 监听
print('waiting the call')
conn,addr = server.accept() # 等电话打进来,并且返回连接对象,
print(conn)
print('the call has comming')
data = conn.recv(1024) #接收客户端的消息,这里是一个字符串
print('data:',data.decode()) # 将接受的数据进行解码
conn.send(data.upper()) # 将字符串变成大写后发生给客户端
2,客户端代码:在windows上运行,实现先发送在接收的功能。代码如下:
import socket
client = socket.socket() # 有一些默认参数,即可使用ipv4,这一句是声明socket类型和返回socket连接对象
client.connect(("192.168.1.105",6969)) # 建立连接:传入服务器端IP号和要连接的应用程序的端口号
#client.send(b'Hello') # 这里只能发生字节流信息,否则报错
client.send('我是Hello'.encode(encoding='utf-8')) # 需要变成utf-8编码形式
data = client.recv(1024) #客户端可以接收服务器端的消息
print(data.decode())
client.close()
运行步骤:
1先在Ubuntu下运行服务器端代码:产生效果如下:
2在windows运行客户端代码:服务器端效果改变了如下:
3,windows客户端效果如下:
上面代码的缺点:
一个人只能说一句话,而且服务器端断开一个连接后服务器也就断开了。
目的:一个客户端可以说很多话,客户端断开后,服务器端接待下一个客户端,继续说话。
在上面的基础上做一些简单的改进
'''
服务器端:
'''
import socket
server = socket.socket()
server.bind(("localhost",6969)) #绑定要监听的端口port
server.listen() # 监听
print('waiting the call')
while True:
conn,addr = server.accept() # 等电话打进来,每个conn代表一个客户端的连接
print(conn)
print('the call has comming')
while True:
data = conn.recv(1024)
if not data :
print('this user is end,exit!\n next user')
break
print('data:',data.decode())
conn.send(data.upper()) #服务器发送有最大值限制,比如32192M(瞎说的),使用sendall这个函数可以,
但是客户端不能接受很多,事实上ssh确实有接受最大值限制
'''
客户端---------------------------------------
'''
import socket
client = socket.socket() # 有一些默认参数,即可使用ipv4,这一句是声明socket类型和返回socket连接对象
client.connect(("localhost",6969))
while True:
msg = input("massage:").strip()
if len(msg)==0:
continue
client.send(msg.encode(encoding='utf-8')) # 不能发空的东西
data = client.recv(1024)
print(data.decode())
client.close()
应用
可以模拟做一个ssh客户端:在上面客户端输入命令如bash命令,客户端可以返回一个结果比如ls命令,
只需在服务器端修改代码即可。在服务器中收到的字符串将其转换为bash命令并且执行即可,使用os模块。