将上面的一个收发消息程序再封装一次,面向对象编程。先贴出上一篇整理的代码:
from socket import * #补
from threading import Thread #补
import sys #补
def udpsend():
sendaddr = ("172.20.10.3",8877) # 确定发送ip地址和端口
while True:
senddata = input('<<') # 确定要发送的信息
udpsocket.sendto(senddata.encode("gb2312"), sendaddr) # 发送信息,这里用Gb2312编码是因为网络调试助手是用GB2312编码的。通常用utf-8编码。
def udprecv():
while True:
result = udpsocket.recvfrom(1024)
sys.stdout.write('r%s%sn' % (">>", result[0].decode("gb2312")))
sys.stdout.flush()
sys.stdout.write("r%s" % ('<<'))
sys.stdout.flush()
udpsocket = None #补
def main():
global udpsocket #补,因为接受和发送都需要用到套接字,所以要全局化
udpsocket = socket(AF_INET, SOCK_DGRAM) # 创建套接字,现在用的是udp,还有一种tcp
udpsocket.bind(("", 5566)) #补,绑定端口,接收消息
thread_send = Thread(target=udpsend)
thread_recv = Thread(target=udprecv)
thread_send.start()
thread_recv.start()
thread_send.join()
thread_recv.join()
if __name__ == '__main__':
main()
这么多代码,怎么封装呢?把什么提出来做属性和方法?
还是回到了起点。我们要实现什么?----我们就是想实现发消息和收消息这个功能,恩,那这两个就是要定义的方法。还要同时进行啊,还那封装到另一个方法里调用。那属性是什么呢?想了半天,我知道了谁的ip,port和自己要绑定的port,就可以和他聊天了啊,也就是传这三个参数就可以了。
from socket import *
from threading import Thread
import sys
class Simutalk(object):
def __init__(self,sendaddr,port): #绑定属性
self.sendaddr = sendaddr
self.port = port
def udpsend(self): #定义发送消息函数
while True:
self.senddata = input('<<') # 确定要发送的信息
self.udpsocket.sendto(self.senddata.encode("gb2312"), self.sendaddr) # 发送信息,这里用Gb2312编码是因为网络调试助手是用GB2312编码的。通常用utf-8编码。
def udprecv(self):
while True:
self.result = self.udpsocket.recvfrom(1024)
sys.stdout.write('r%s%sn' % (">>", self.result[0].decode("gb2312")))
sys.stdout.flush()
sys.stdout.write("r%s" % ('<<'))
sys.stdout.flush()
def threads(self): #定义多线程函数,调用收发消息函数
self.crea_socket()
self.thread_send = Thread(target=self.udpsend)
self.thread_recv = Thread(target=self.udprecv)
self.thread_send.start()
self.thread_recv.start()
self.thread_send.join()
self.thread_recv.join()
def crea_socket(self): #这里我把剩下的都放一起了。。。其实我也不知道合不合适,不过是对的
self.udpsocket = socket(AF_INET, SOCK_DGRAM) # 创建套接字,现在用的是udp,还有一种tcp
self.udpsocket.bind(("", self.port))
调用结果:
import Socket7 #导入模块要在一个路径导,不然找不到的(上一个程序的名字我命名为Socket7)
firsttalk = Socket7.Simutalk(("172.20.10.3", 8877),5566) #实例化,传三个参数(目标ip,port,我要绑定的port)
firsttalk.threads()
![b0a6cba02f12ca773f1bea76ca5a2d24.png](https://i-blog.csdnimg.cn/blog_migrate/a09eba35640ea9e0dc35f9b59c9a9a27.jpeg)
绑定port的问题是,如果没有绑定,但是我先给对方发消息,它有了我的ip和port之后是可以和我发消息的;要是我没有绑,对方是没法先给我发消息的,因为它不知道我的port。
对上面的代码稍作更改,只是结构上的,上面代码运行起来也没有问题。(下面这段代码不作模块导入使用,要作为模块使用需要更改main函数位置)
#coding = utf-8
from socket import *
from threading import Thread
import sys
class Simutalk(object):
def __init__(self): #这里做了一点改变,简化实例化时传参的过程
self.udpsocket = socket(AF_INET, SOCK_DGRAM) # 创建套接字,现在用的是udp,还有一种tcp
self.sendaddr = (input("请输入对方ip:"), int(input("请输入对方端口:")))
def udpsend(self):
while True:
self.senddata = input('<<') # 确定要发送的信息
self.udpsocket.sendto(self.senddata.encode("gb2312"), self.sendaddr) # 发送信息,这里用Gb2312编码是因为网络调试助手是用GB2312编码的。通常用utf-8编码。
def udprecv(self):
while True:
self.result = self.udpsocket.recvfrom(1024)
sys.stdout.write('r%s%sn' % (">>", self.result[0].decode("gb2312")))
sys.stdout.flush()
sys.stdout.write("r%s" % ('<<'))
sys.stdout.flush()
def threads(self):
self.thread_send = Thread(target=self.udpsend)
self.thread_recv = Thread(target=self.udprecv)
self.thread_send.start()
self.thread_recv.start()
self.thread_send.join()
self.thread_recv.join()
def bind(self, port):
self.udpsocket.bind(("", port))
def main():
simutalk = Simutalk()
simutalk.bind(7788) #这里做了改变,为了简化传参,将端口拿出来通过bind函数绑定
simutalk.threads()
if __name__ == '__main__':
main()
更改的主要思想是:
一,练习创建接口,通过调用主函数实现整个程序的运行。
二,将一开始就要用到的或者需要创建的变量放到构造函数里完成,比如上面的,就省去了最后还要定义create_socket(self)函数的步骤。
三,一定要注意整体结构,这里main()和class()是并列的,是为了就在当前界面运行看结果,如果想要导入模块使用,就要改下了,不然会有点小问题。
下面代码作为模块导入
from socket import *
from threading import Thread
import sys
def main():
class Simutalk(object):
def __init__(self):
self.udpsocket = socket(AF_INET, SOCK_DGRAM) # 创建套接字,现在用的是udp,还有一种tcp
self.sendaddr = (input("请输入对方ip:"), int(input("请输入对方端口:")))
def udpsend(self):
while True:
self.senddata = input('<<') # 确定要发送的信息
self.udpsocket.sendto(self.senddata.encode("gb2312"),
self.sendaddr) # 发送信息,这里用Gb2312编码是因为网络调试助手是用GB2312编码的。通常用utf-8编码。
def udprecv(self):
while True:
self.result = self.udpsocket.recvfrom(1024)
sys.stdout.write('r%s%sn' % (">>", self.result[0].decode("gb2312")))
sys.stdout.flush()
sys.stdout.write("r%s" % ('<<'))
sys.stdout.flush()
def threads(self):
self.thread_send = Thread(target=self.udpsend)
self.thread_recv = Thread(target=self.udprecv)
self.thread_send.start()
self.thread_recv.start()
self.thread_send.join()
self.thread_recv.join()
def bind(self, port):
self.udpsocket.bind(("", port))
simutalk = Simutalk()
simutalk.bind(7788)
simutalk.threads()
if __name__ == '__main__':
main()
调用效果
![bca8b97b14cbc36eaaed995e12698380.png](https://i-blog.csdnimg.cn/blog_migrate/c4dd9b2b2f87c448c3aecd527d1a4061.png)