python 网络编程学习 1
参考链接: http://HdhCmsTestiteye测试数据/topic/401391
http://HdhCmsTestcppblog测试数据/lai3d/archive/2008/02/19/42919.html
套接字
首先,我们应先理解什么事套接字。套接字是一种具有之前所说的“通信端点”概念的计算机网络数据结构。网络化的应用程序在开始任何通讯之前都必须要创建套接字。就像电话的插口一样,没有它就没办法通信。
套接字有两种,分别是基于文件型的和基于网络型的。
套接字家族包括AF_UNIX,AF_LOCAL,AF_INET和AF_NETLINK。
python只支持AF_UNIX,AF_INET和AF_NETLINK。因我们只关心网络编程,所以我们只用AF_INET。
SOCKET()模块
套接字模块是一个非常简单的基于对象的接口,它提供对低层BSD套接字样式网络的访问。使用该模块可以实现客户机和服务器套接字。要在python 中建立具有TCP和流套接字的简单服务器,需要使用socket模块。利用该模块包含的函数和类定义,可生成通过网络通信的程序。
socket内建方法
连接方式分TCP和UDP两种
分别看一下
TCP方式
server端
server端的socket一般流程是这样:
1. 建立一个socket(可以选择socket类型INET,UNIX等,以及连接方式TCP/UDP)
socket=socket.socket(familly,type)
family的值可以是AF_UNIX(Unix域,用于同一台机器上的进程间通讯),也可以是AF_INET(对于IPV4协议的TCP和 UDP),至于type参数,SOCK_STREAM(流 套接字)或者 SOCK_DGRAM(数据报文套接字),SOCK_RAW(raw套接字)。
2. 使用bind公开一个端口,使得client可以方便连接
socket.bind(address)
address必须是一个双元素元组,((host,port)),主机名或者ip地址+端口号。如果端口号正在被使用或者保留,或者主机名或ip地址错误,则引发socke.error异常。
3. 设置一个listen队列的大小
socket.listen(backlog)
backlog指定了最多连接数,至少为1,接到连接请求后,这些请求必须排队,如果队列已满,则拒绝请求。
4. 服务器套接字通过socket的accept方法等待客户请求一个连接:
connection,address=socket.accept()
调用accept方法时,socket会进入'waiting'(或阻塞)状态。客户请求连接时,方法建立连接并返回服务器。accept方法返回 一个含有俩个元素的元组,
形如(connection,address)。第一个元素(connection)是新的socket对象,服务器通过它与客 户通信;第二个元素(address)是客户的internet地址。
5. 通过send()/recv()来对socket进行读写操作
服务器调用send,并采用字符串形式向客户发送信息。send方法 返回已发送的字符个数。服务器使用recv方法从客户接受信息。调用recv时,必须指定一个整数来控制本次调用所接受的最大数据量。recv方法在接受 数据时会进入'blocket'状态,最后返回一个字符串,用它来表示收到的数据。如果发送的量超过recv所允许,数据会被截断。多余的数据将缓冲于接 受端。以后调用recv时,多余的数据会从缓冲区删除。
代码示例
import socket s = socket.socket() s.bind(( ' xxx.xxx.xxx.xxx ' ,xxxx)) # ip地址和端口号s.listen(5) cs,address = s.accept() print ' got connected from ' ,address cs.send( ' byebye ' ) ra =cs.recv(512 ) print ra cs.close()
client端
代码示例
import socket s = socket.socket() s.connect(( ' xxx.xxx.xxx.xxx ' ,xxxx)) # 与服务器程序ip地址和端口号相同data=s.recv(512) s.send( ' hihi ' ) s.close() print ' the data received is ' ,data
测试代码
服务器端
# !/usr/bin/python
# -*- coding: utf-8 -*-
import socket
from time import ctime
'''
host为空表示bind可以绑定到所有有效地址上
port 必须要大于1024
bufsiz为缓冲区 我们设置为1K
'''
host = ''
port = 23456
bufsiz = 1024
ADDR = (host,port)
tcpSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen( 5) # 参数表示允许多少连接同时连进来
try :
while True:
'''
进入服务器的无限循环中,等待连接到来
有链接时,进入对话循环,等待客户发送数据,如果消息为空,表示客户端已经退出,等待下一个客户端连接
得到客户端消息后在消息前加一个时间戳后返回
'''
print ' waiting for connection... '
tcpSerSock,addr = tcpSerSock.accept()
print ' ...connected from ' ,addr
while True:
data = tcpSerSock.recv(bufsiz)
if not data:
break
tcpSerSock.send( ' [%s] %s ' % (ctime(),data))
except BaseException, e:
tcpSerSock.close() # 记住在服务器退出时记得关闭
客户端
# !/usr/bin/python
# -*- coding: utf-8 -*-
import socket
host = ' 127.0.0.1 '
port = 23456
bufsiz = 1024
ADDR = (host,port)
tcpCliSock = socket.socket(socket.AF_INET, socket.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()
UDP方式
UDP号称无连接传输,全然没有TCP那么复杂,三次握手,错误重传之类的机制都没有,发的只管发,收得只管收,收到没有?不知道,顺序不对怎么 办?不管!就是这样,但是速度就要比TCP高得多了。在对数据帧要求不是很高的地方,这确实是很好用的,比如网络上的视频传输,音频传输等。
server端
1. 建立数据报形式的socket
2. 公开一个端口,一边客户端连接
3. 开始接收数据
def udpServer():
address = ( ' xxx.xxx.xxx.xxx ' , xxxx )
srvsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
srvsock.bind(address)
# data,addr = srvsock.recvfrom(2048)
if __name__ == " __main__ " :
udpServer()
server中address元组中的引号表示可以接受任何地址来的数据报,TCP例子中的则表示可以接受任意地址发起的连接。
client端
1. 新建一个数据报socket
2. 收发数据
def udpClient():
address = ( ' xxx.xxx.xxx.xxx ' , xxxx)
clisock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# clisock.sendto(data, address)
if __name__ == " __main__ " :
udpClient()
测试代码
服务器端
# !/usr/bin/python
# -*- coding: utf-8 -*-
import socket
from time import ctime
'''
host为空表示bind可以绑定到所有有效地址上
port 必须要大于1024
bufsiz为缓冲区 我们设置为1K
'''
host = ''
port = 23456
bufsiz = 1024
ADDR = (host,port)
udpSerSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udpSerSock.bind(ADDR)
try :
while True:
print ' waiting for connection... '
data,addr = udpSerSock.recvfrom(bufsiz)
udpSerSock.sendto( ' [%s] %s ' % (ctime(),data),addr)
if data == ' exit ' :
break
print ' ...received from and returned to: ' ,addr
except BaseException, e:
print e
udpSerSock.close()
客户端
# !/usr/bin/python
# -*- coding: utf-8 -*-
import socket
host = ' 127.0.0.1 '
port = 23456
bufsiz = 1024
ADDR = (host,port)
udpCliSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
data = raw_input( ' > ' )
if not data:
break
udpCliSock.sendto(data,ADDR)
data,ADDR = udpCliSock.recvfrom(bufsiz)
if not data:
break
print data
udpCliSock.close()
作者: GoodSpeed Cheng
出处: http://HdhCmsTestcnblogs测试数据/cacique/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息