Python-Socket通信

很久之前Python就业班就已经学过了,昨天回头看朋友的面经发现他面试的过程被问到这方便的问题,回头想想记忆有点模糊了,重写一篇博客重点复习下Socket通信。

什么是socket

创建socket

在Python中使用socket模块的函数socket就可以完成

1
socket.socket(AddressFamily,Type)

创建TCP Socket

创建tcp套接字

1
2
3
import socket

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

创建UDP Socket

创建udp套接字

1
2
3
import socket

s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

UDP网络程序

准备一台虚拟机和本机,进行通信。

本机Mac ip:10.211.55.2

虚拟机Centos ip:10.211.55.23

UDP发送数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from socket import *

from django.dispatch import receiver


#1、创建套接字
udpSocket = socket(AF_INET,SOCK_DGRAM)

#2、接收方地址,端口
sendAddr = ('10.211.55.23',8888)

#3、要发送的数据
sendData = input("输入要发送的数据:")

#4、发送数据到指定接收方
udpSocket.sendto(sendData.encode('utf-8'),sendAddr)

#7、关闭套接字
udpSocket.close()

虚拟机直接用nc进行监听来接收数据

image-20220728182756695

UDP发送 接收数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from socket import *

from django.dispatch import receiver


#1、创建套接字
udpSocket = socket(AF_INET,SOCK_DGRAM)

#2、接收方地址,端口
sendAddr = ('10.211.55.23',8888)

#3、要发送的数据
sendData = input("输入要发送的数据:")

#4、发送数据到指定接收方
udpSocket.sendto(sendData.encode('utf-8'),sendAddr)

#5、等待对方发送数据
recvData = udpSocket.recvfrom(1024) #1024最大可接收的字节

#6、显示对方发送的数据
print(recvData)

#7、关闭套接字
udpSocket.close()

image-20220728170646989

hacker是我本机Mac发送到CentOs的数据

1 是CentOs回本机Mac的数据

UDP端口绑定 接收数据

上面的发送 接收数据代码其实并不是很完善

接收数据应该有一个绑定端口的过程

发送方不需要绑定端口,接收方(服务方)一定要绑定,不然发送方是很难找到我们并发送数据给我们的

1
2
bindAddr = ('',7788)#ip地址和端口号,ip一般不写,表示本机的任何一个ip
udpSocket.bind(bindAddr)

ip一般不写,表示任何一个ip都是可以的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from socket import *


#1、创建套接字
udpSocket = socket(AF_INET,SOCK_DGRAM)

#2、绑定端口
bindAddr = ("",7788)
udpSocket.bind(bindAddr)

#3、sendto发送数据,revfrom接收数据,1024表示接收的最大字节数
recvData = udpSocket.recvfrom(1024)
content,destInfo = recvData

print("content is %s"%content)
print("content is %s"%content.decode("utf-8"))

#4、关闭套接字
udpSocket.close()

简单聊天室

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from socket import *

def main():
udpSocket = socket(AF_INET,SOCK_DGRAM)
udpSocket.bind(("",6789))

#收,打印
while True:
recvInfor = udpSocket.recvfrom(1024)
print("[%s]:%s"%(str(recvInfor[1]),recvInfor[0].decode("gb2312")))


if __name__ == "__main__":
main()

image-20220801114359211

echo服务器

echo服务器 简单说就是,你给我发一个东西我给你回一个。

比咱们上面的程序就多了一句话。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from socket import *

def main():
udpSocket = socket(AF_INET,SOCK_DGRAM)
bindAddr = ('',7788)
udpSocket.bind(bindAddr)

num = 1
while True:
#等待接收对方发送的数据
recvData = udpSocket.recvfrom(1024)
#接收的数据在发给对方,recvData[0]是数据内容,recvData[1]是ip端口信息
udpSocket.sendto(recvData[0],recvData[1])
print("[%s]:%s"%(str(recvData[1]),recvData[0].decode("gb2312")))


if __name__ == "__main__":
main()

image-20220801152639642

可见我们发送完数据以后能成功返回来。

模拟QQ聊天(多线程)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
from threading import Thread
from socket import *


#1、收数据,后打印
def recvData():
while True:
recvInfo = udpSocket.recvfrom(1024)
#recvInfo[1]是ip端口数据,recvInfo[0]是内容
print(">>%s:%s"%(str(recvInfo[1]),recvInfo[0].decode("gb2312")))

#2、检测键盘发数据
def sendData():
while True:
sendInfo = input("<<")

udpSocket.sendto(sendInfo.encode("gb2312"),(destIp,destPort))

udpSocket = None
destIp = ""
destPort = 0

def main():
#声明全局变量
global udpSocket
global destIp
global destPort
udpSocket = socket(AF_INET,SOCK_DGRAM)
udpSocket.bind(("",4567))

destIp = input("对方的ip")
destPort = int(input("对方的端口"))

#两个线程
tr = Thread(target=recvData)
ts = Thread(target=sendData)

tr.start()
ts.start()

tr.join()#等待tr进程结束以后往下走
ts.join()


if __name__ == "__main__":
main()