Python网络编程学习笔记(TCP/UDP)
本笔记总结了Python网络编程相关知识点。
1.套接字家族
Python只支持AF_UNIX、AF_NETLINK、AF_INET,在以下学习中,我们只用到了AF_INET。
2.面向连接和无连接
面向连接TCP:SOCK_STREAM(数据流),流套接字
面向无连接UDP:SOCK_DGRAM (数据报)
2.1 TCP服务器/客户端示例
以下代码示例完成这样的简单功能:服务器启动后进入循环监听,客户端创建后向服务器发送连接请求。连接建立后,服务器显示客户端信息,随后客户端将输入的文本消息发送给服务器,服务器将信息打上当前时间戳后回传给客户端,直至客户端异常关闭(输入为空或接收为空)后,关闭连接。
TCP服务器代码 testTserver.py
#coding=utf-8 #这一行指定了本代码的编码格式。由于本代码中存在中文注释,如果不加这一行,运行本文时会报错。
#! usr/bin/env python
from socket import * #导入socket模块
from time import ctime #导入时间模块
HOST='127.0.0.1' #绑定地址(这里设置为本地地址,如果为空则表示可以绑定在所有有效地址)
PORT=21567 #设定端口号
BUFSIZE=1024 #设定缓冲区的大小
ADDR=(HOST,PORT) #主机地址+端口号 共同确定了端口的属性
tcpSerSock=socket(AF_INET,SOCK_STREAM) #创建一个基于数据流的tcp服务器,协议簇为AF—INET
tcpSerSock.bind(ADDR) #将这个服务器绑定在端口ADDR上
tcpSerSock.listen(5) #调用侦听方法,设定最大连接数为5(超过了就不连了)
while True:
print 'Waiting for connection......'
tcpCliSock,addr=tcpSerSock.accept() #监听得到客户端信息(这个方法有两个返回值)
print '...Connected from:',addr
while True:
data=tcpCliSock.recv(BUFSIZE) #接收客户端传来的文本消息
if not data:
break
tcpCliSock.send('[%s] %s' % (ctime(),data))
#tcpCliSock.close() #原例子中存在这一行,但实际运行时需要注释掉,否则C/S两端完成一次信息来回后,服务器端就将客户端关闭了。可能引起奇怪的报错。
tcpSerSock.close() #由于死循环的存在,一般不会执行到这里。提醒在服务器编程里需要注意留出口给关闭功能。
TCP客户端代码 testTclient.py
!/usr/bin/env python
from socket import *
HOST='localhost' #试验时在同一台主机上,故也设为localhost(等价本地地址)
PORT=21567
BUFSIZ=1024
ADDR=(HOST,PORT)
tcpCliSock=socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)
while True:
data=raw_input('>')
if not data:
break
tcpCliSock.send(data) #将输入的文本传输给服务器端
data=tcpCliSock.recv(BUFSIZ) #接受服务器端回传的文本消息
if not data:
break
print data #输出服务器回传的文本信息(时间戳+发送信息)
tcpCliSock.close()
运行后结果如下:
先运行服务器——
[root@localhost TCP]# python testTserver.py
Waiting for connection......
...Connected from: ('127.0.0.1', 35790)
再运行客户端——
[root@localhost TCP]# python testTclient.py >a [Thu Apr 10 14:49:32 2014] a >b [Thu Apr 10 14:49:33 2014] b >c [Thu Apr 10 14:49:34 2014] c >d [Thu Apr 10 14:49:35 2014] d >test [Thu Apr 10 14:49:37 2014] test >
提示:在实际的应用中,一种非常常用的手段是:服务器端通过创建新的进程/线程来与客户端通信。本例中并未实现这样的功能。此外,在Python编程中,缩进符的实现(空格还是TAB)往往会引发奇怪的报错,在编写代码过程中需要时刻注意。
在实际编程应用中,还需要留意设计智能的退出方案,防止进入死循环。
2.2 UDP服务器/客户端示例
UDP服务器代码 testUserver.py
#! usr/bin/env python
from socket import *
from time import ctime
HOST='127.0.0.1'
PORT=21567
BUFSIZE=1024
ADDR=(HOST,PORT)
udpSerSock=socket(AF_INET,SOCK_DGRAM) #注意由于是无连接,参数为SOCK_DGRAM,另外由于是无连接,不需要启用侦听函数
udpSerSock.bind(ADDR)
while True:
print 'Waiting for message......' #这里我们用的是message而不是connection
data,addr=udpSerSock.recvfrom(BUFSIZE) #注意区别TCP和UDP调用函数名称的差异
udpSerSock.sendto('[%s] %s' % (ctime(),data),addr)
print '...received from and returned to:',addr
udpSerSock.close()
UDP客户端代码 testUclient.py
#!/usr/bin/env python
from socket import *
HOST='localhost'
PORT=21567
BUFSIZ=1024
ADDR=(HOST,PORT)
udpCliSock=socket(AF_INET,SOCK_DGRAM) #这里与TCP的区别在于无需先建立连接,直接把输入的文本发到绑定的端口就完了,随后等着收返回消息。
while True:
data=raw_input('>')
if not data:
break
udpCliSock.sendto(data,ADDR)
data,addr=udpCliSock.recvfrom(BUFSIZ)
if not data:
break
print data
tcpCliSock.close()
运行代码后试验结果也是与TCP的大同小异。
3.总结比较
对于TCP的C/S编程,服务器端需要先绑定一个端口(主机+端口号),然后通过监听有无客户端的连接申请来实现通信。客户端通过绑定的端口建立专有连接后,方可进行文本通信。而对于UDP的C/S编程中,服务器和客户端只要完成接收和发送信息的功能即可,不需要实现“监听-连接”的过程。
浙公网安备 33010602011771号