UDP实现
UDP属于无连接协议,在编程时不需要建立连接,而是直接向接收方发送信息。UDP不提供应答重传机制,无法保证数据一定能够到达目的地。UDP编程经常用到socket模块方法如下所示:
UDP协议优点:效率高、首部中只包含双方地址与校验和等很少的字段,额外开销小。
实验代码:
udp_server.py(服务端)
import socket
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 创建socket对象,AF_INET代表使用ipv4,SOCK_DGRAM代表协议为udp
s.bind(('', 8001)) # bind绑定端口
while True:
data, addr = s.recvfrom(1024) # recvfrom()接收信息
print(data.decode()) # 输出在终端上
if data.decode().lower() == 'bye': # 接收到bye即退出程序
break
s.close()
udp_client.py(发送端)
import socket
import uuid
import sys
def get_mac_address():
mac = uuid.UUID(int=uuid.getnode()).hex[-12:] # 通过uuid获得本机mac地址
return ":".join([mac[e:e+2] for e in range(0, 11, 2)])
ip = socket.gethostbyname(socket.gethostname()) # 获得本机ip地址
mac = get_mac_address()
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 创建socket对象
info = "ip addr:"+ip+"\n"+"mac addr:"+mac
s.sendto(info.encode(), ("127.0.0.1", 8001)) # 向本地8001端口发送信息
s.sendto(sys.argv[1].encode(), ("127.0.0.1", 8001))
s.close()
这里的mac地址是uuid获得的
通过uuid获得的字符串是00000000-0000-0000-0000-00bb600775aa
import uuid
print(uuid.UUID(int=uuid.getnode()))
00000000-0000-0000-0000-00bb600775aa
最后几位就是mac地址
运行效果:
TCP实现
TCP一般用于可靠数据传输的场合, TCP编程经常用到socket模块方法如下所示:
创建套接字
socket.socket(family,type)
- family: 套接字家族AF_UNIX 或者 AF_INET
- type: 套接字类型SOCK_STREAM或SOCK_DGRAM
Socket 对象(内建)方法
服务器端套接字
函数 | 描述 |
---|---|
s.bind() | 绑定地址(host,port)到套接字,以元组形式表示地址。例: s.bind((‘127.0.0.1’,80)) |
s.listen() | 开始TCP监听。里面参数代表可以挂起的最大连接数量,至少为1。例: s.listen(1) |
s.accept() | 接受一个tcp客户端连接。例: conn, addr = s.accept() |
客户端套接字
函数 | 描述 |
---|---|
s.connect() | 连接客户端。例: s.connect((‘127.0.0.1’, 8002)) |
s.connect_ex() | connect()函数的扩展版本,出错时返回出错码,而不是抛出异常 |
公共用途的套接字函数
函数 | 描述 |
---|---|
s.recv() | 接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。例: data = conn.recv(1024).decode() |
s.send() | 发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。 |
s.sendall() | 完整发送TCP数据,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。例: conn.sendall(c.encode()) |
s.close() | 关闭套接字 |
实验代码:
tcp_server.py(服务端)
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 使用ipv4,tcp协议
s.bind('', 8002)
s.listen(1) # 最大连接数
conn, addr = s.accept() # accept()接受一个连接
print('connected by', addr)
while True:
data = conn.recv(1024).decode()
print("从用户方接受到数据:", data)
c = input("发送给用户:")
conn.sendall(c.encode())
if c.lower() == 'bye':
break
conn.close()
s.close()
tcp_client.py(用户)
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect(('127.0.0.1', 8002))
except Exception as e:
print("连接失败,错误原因:", e)
else:
while True:
c = input('输入想要发送的信息:')
s.sendall(c.encode())
data = s.recv(1024).decode()
print("接收到信息:", data)
if c.lower() == 'bye':
break
s.close()
实验结果:
拓展
实验代码:
import socket
hostname = socket.gethostname()
ip = socket.gethostbyname(hostname)
ip_bai = socket.gethostbyname("www.baidu.com")
host = socket.gethostbyaddr(ip)
sername = socket.getservbyport(80, 'tcp')
port = socket.getservbyname('http')
print("gethostname:", hostname)
print("gethostbyname:", ip)
print("gethostbyname:", ip_bai)
print("gethostbyaddr:", host)
print("getservbyport:", sername)
print("getservbyname:", port)