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编程中,服务器和客户端只要完成接收和发送信息的功能即可,不需要实现“监听-连接”的过程。

posted on 2014-04-10 14:56  superfox  阅读(154)  评论(0)    收藏  举报

导航