python学习心得之:socket实现终端对话
我们可以使用python在本地搭建简易服务器,所谓简易服务器,其实便是两台计算机通过python实现通话,就像我们使用的qq聊天软件。
在实现即时通话之前,我们需要进行一个基础知识的学习-client嵌套字。
一、socket
定义
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
我们在可以不去深究scoket内在的运行的机制,在使用python编程时只需要了解并会使用scoket的一些内建函数便可以实现基本的功能,以下是我总结的一些内建函数,秉着用多少学多少的原则,我这里并不列举所有的内容。
序号 | 内建函数 | 参数 | 返回值 | 功能 |
---|---|---|---|---|
服务器端 | ||||
1 | bind((host, port)) | 这里的(host,port)不是两个参数,而是一个元组形式参数,其中host为主机名,port为端口 | 无 | 绑定地址到嵌套字 |
2 | listen(num) | num为指定在拒绝连接之前,可以挂起的最大连接数量,最小为1,最大为5 | 无 | 开始TCP监听 |
3 | accept() | 无 | 这里的返回值是一个元组形式,内容较为复杂,可以不去深究,我们可以利用这个返回值去进行收发数据,例如在我电脑上返回值如下(<socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=(‘192.168.0.100’, 8002), raddr=(‘192.168.0.100’, 50688)>, (‘192.168.0.100’, 50688)) | 本方法会阻塞线程,直到有客户端连入 |
客户端 | ||||
1 | connect((host, port)) | 这里的参数仍然是一个元组形式,内容和服务器端bind()方法的参数是一样的 | 无 | 实现与服务器的连接 |
公共方法 | ||||
1 | recv() | 不详细解释 | 对方发送的数据 | 接收数据 |
2 | send() | 要发送的数据 | 无 | 发送数据 |
socket内建的方法还有很多,本次练习只用到这些,先介绍这么多
二、socket实现本地通话
我们先来看一段代码
#服务器端
import socket
s = socket.socket()
host = socket.gethostname() #获取主机名
port = 9000 #端口
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept() #阻塞进程,等待客户端接入
c.send(bytes("连接成功?",encoding="utf-8")) #客户端接入,发送数据
c.close()
#客户端
import socket
s = socket.socket()
host = socket.gethostname() #获取主机名
port = 9000 #端口
s.connect((host, port)) #客户端接入
mes = str(s.recv(1024),encoding = "utf-8") #接收客户端数据
print("服务器:{}".format(mes)) #打印输出
s.close()
这段代码比较简单,将我们上面介绍的内建方法做一个调用,然后讲收到的数据做一个打印输出,各位不妨试一试,在同一台电脑上,打开两个终端,分别运行两个程序,你大概会得到如下的结果。
到这里,我们实现了一个最简单的功能:连接服务器-接受服务期的消息-打印输出
然而这显然是不够的,我们可以看到,左上角的服务器端一直在运行,而左下角的客户端在接收数据后就退出了,而如何实现他们之间的对话?
我们接着看下一段代码:
#服务器端
import socket
s = socket.socket()
host = socket.gethostname()
port = 9000
s.bind((host, port))
s.listen(5)
while True:
print('等待用户连接……')
c, addr = s.accept() #阻塞进程,等待客户端接入
print('用户已连接 address:{}\n服务器:请问需要什么帮助'.format(addr))
c.send(bytes("请问需要什么帮助?",encoding="utf-8"))
while True:
mes = str(c.recv(1024),encoding = "utf-8")
print("客户端:{}".format(mes))
mes = input("服务器:")
c.send(bytes(mes,encoding="utf-8"))
c.close()
import socket
s = socket.socket()
host = socket.gethostname()
port = 9000
s.connect((host, port)) #客户端接入
while True:
mes = str(s.recv(1024),encoding = "utf-8")
print("服务器:{}".format(mes))
mes = input("客户端:")
s.send(bytes(mes,encoding="utf-8"))
s.close()
在这段代码中,我对界面做了一些优化,我们可以看到,借用一个简单的循环,我们实现了两个终端之间的对话,你可以尝试一下,在同一台电脑上,打开两个终端,分别运行两个程序,你会得到如下的结果。
三、计算机间通讯
我不知道各位有没有留意到我刚才一直提到“在同一台电脑上”,事实上,若是你使用上面的代码,在不同的计算机上运行,必然是会报错的,那是因为,我们的服务器和客户端的host都是socket.gethostname(),这句代码是用来获取本机的hostname的,很显然,如果你想实现两台设备之间的通讯,则必须把客户端的host改为服务器端的host。
四、结论
到了这里,其实相信各位也看明白了,python搭建简易的服务器其实完全可以套路化
#服务器端
import socket
s = socket.socket()
host = socket.gethostname()
port = 9000
s.bind((host, port))
s.listen(5)
c, addr = s.accept()
#you code here
#客户端
import socket
s = socket.socket()
host = "服务器host"
port = "服务器port"
s.connect((host, port))
#you code here
s.close()
你只需要将你希望计算机做出的反应填写在#you code here处即可
五、Demo
说了这么多,下面附上我做的一个小demo
#服务器端
import socket
s = socket.socket()
host = socket.gethostname()
port = 8000
s.bind((host, port))
s.listen(5)
while True:
print("="*100)
print('等待用户连接……')
c, addr = s.accept()
print('用户已连接 address:{}\n{}\n服务器:请问需要什么帮助'.format(addr,"-"*50))
c.send(bytes("请问需要什么帮助?输入quit结束对话",encoding="utf-8"))
while True:
mes = str(c.recv(1024),encoding = "utf-8")
print("客户端:{}".format(mes))
if mes == "quit":
c.send(bytes("再见",encoding="utf-8"))
break
mes = input("服务器:")
c.send(bytes(mes,encoding="utf-8"))
c.close()
#客户端
import socket
s = socket.socket()
host = socket.gethostname()
port = 8000
s.connect((host, port))
while True:
mes = str(s.recv(1024),encoding = "utf-8")
print("服务器:{}".format(mes))
if mes == "再见":
break
mes = input("客户端:")
s.send(bytes(mes,encoding="utf-8"))
s.close()
实现效果如下图:
六、总结
本文详细介绍了python搭建简易服务器的过程,然而技术是复杂的,下面总结一些问题,留待以后学习解决:
1.本文中服务器最大监听数量为5,后连接的客户端需要等待,然而我尝试修改该数字为1,仍然可以继续等待
2.如何使拂去其向等待的客户端发送等待通知
3.本文中服务器与客户端交替进行交流对话,如若乙方连续发送,则会出现一定的混乱,如何解决?
以上就是本文的全部内容,欢迎各位一同交流学习。