python网络编程学习笔记(三):socket网络服务器


Posted in Python onJune 09, 2014

1、TCP连接的建立方法

客户端在建立一个TCP连接时一般需要两步,而服务器的这个过程需要四步,具体见下面的比较。

步骤 TCP客户端 TCP服务器
第一步 建立socket对象  建立socket对象
第二步 调用connect()建立一个和服务器的连接 设置socket选项(可选)
第三步 绑定到一个端口(也可以是一个指定的网卡)
第四步 侦听连接

下面具体来讲这四步的建立方法:

第一步,建立socket对象:这里与客户端一样,依然是:

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

第二步,设置和得到socket选项

python定义了setsockopt()和getsockopt(),一个是设置选项,一个是得到设置。这里主要使用setsockopt(),具体结构如下:

setsockopt(level,optname,value)

level定义了哪个选项将被使用。通常情况下是SOL_SOCKET,意思是正在使用的socket选项。它还可以通过设置一个特殊协议号码来设置协议选项,然而对于一个给定的操作系统,大多数协议选项都是明确的,所以为了简便,它们很少用于为移动设备设计的应用程序。

optname参数提供使用的特殊选项。关于可用选项的设置,会因为操作系统的不同而有少许不同。如果level选定了SOL_SOCKET,那么一些常用的选项见下表:

选项 意义 期望值
SO_BINDTODEVICE 可以使socket只在某个特殊的网络接口(网卡)有效。也许不能是移动便携设备 一个字符串给出设备的名称或者一个空字符串返回默认值
SO_BROADCAST 允许广播地址发送和接收信息包。只对UDP有效。如何发送和接收广播信息包 布尔型整数
SO_DONTROUTE 禁止通过路由器和网关往外发送信息包。这主要是为了安全而用在以太网上UDP通信的一种方法。不管目的地址使用什么IP地址,都可以防止数据离开本地网络 布尔型整数
SO_KEEPALIVE 可以使TCP通信的信息包保持连续性。这些信息包可以在没有信息传输的时候,使通信的双方确定连接是保持的 布尔型整数
SO_OOBINLINE 可以把收到的不正常数据看成是正常的数据,也就是说会通过一个标准的对recv()的调用来接收这些数据 布尔型整数
SO_REUSEADDR 当socket关闭后,本地端用于该socket的端口号立刻就可以被重用。通常来说,只有经过系统定义一段时间后,才能被重用。 布尔型整数

本节在学习时,用到了SO_REUSEADDR选项,具体写法是:

S.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 这里value设置为1,表示将SO_REUSEADDR标记为TRUE,操作系统会在服务器socket被关闭或服务器进程终止后马上释放该服务器的端口,否则操作系统会保留几分钟该端口。

下面的方法可以帮助给出该系统下python所支持的socket选项列表:

import socket
solist=[x for x in dir(socket) if x.startswith('SO_')]
solist.sort()
for x in solist:
    Print x

第三步:绑定socket

绑定即为服务器要求一个端口号。

S.bind((host,port)),其中host为服务器ip,通常为空,也可以绑定到一个特定的ip地址。Port为端口号。

第四步:侦听连接。

利用listen()函数进行侦听连接。该函数只有一个参数,其指明了在服务器实际处理连接的时候,允许有多少个未决(等待)的连接在队列中等待。作为一个约定,很多人设置为5。如:s.listen(5)

2、简单的TCP服务器实例
 
        这个建立一个简单的TCP服务器和客户端。

服务器端:TCP响应服务器,当与客户端建立连接后,服务器显示客户端ip和端口,同时将接收的客户端信息和'I get it!'传给客户端,此时等待输入一个新的信息传给客户端。

客户端:TCP客户端,首先输入服务器ip地址,然后输入信息,回车后会得到服务器返回信息,然后等待服务器向其发送信息后退出。

具体代码如下:
服务器端:tcpserver.py

# -*- coding: cp936 -*-
##tcp响应服务器,当与客户端建立连接后,服务器显示客户端ip和端口,同时将接收的客户端信息和'I get it!'传给客户端,此时等待输入一个新的信息传给客户端。
##@小五义
import socket,traceback
host=''
port=12345
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind((host,port))
s.listen(1)
while 1:
    try:
        clientsock,clientaddr=s.accept()
    except KeyboardInterrupt:
        raise
    except:
        traceback.print_exc()
        continue
    try:
        print "连接来自:",clientsock.getpeername()
        while 1:
            data=clientsock.recv(4096)
            if not len(data):
                break
            print clientsock.getpeername()[0]+':'+str(data)
            clientsock.sendall(data)
            clientsock.sendall("\nI get it!\n")
            t=raw_input('input the word:')
            clientsock.sendall(t)
    except (KeyboardInterrupt,SystemExit):
        raise
    except:
        traceback.print_exc()
    try:
        clientsock.close()
    except KeyboardInterrupt:
        raise
    except:
        traceback.print_exc()

客户端:tcpclient.py

# -*- coding: cp936 -*-
##tcp客户端,首先输入服务器ip地址,然后输入信息,回车后会得到服务器返回信息,然后等待服务器向其发送信息后退出。
##@小五义 
import socket,sys
port=12345
host=raw_input('输入服务器ip:')
data=raw_input('输入要发送的信息:')
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
    s.connect((host,port))
except:
    print '连接错误!'
s.send(data)
s.shutdown(1)
print '发送完成。'
while 1:
    buf=s.recv(4096)
    if not len(buf):
        break
    sys.stdout.write(buf)

执行结果:

客户端输入hello,服务器端输入ok,具体显示结果是:

服务器端:

连接来自:('127.0.0.1',1945)
127.0.0.1:hello
Input the world:ok
客户端:
输入服务器ip:127.0.0.1
输入要发送的信息:hello
发送完成。
hello
I get it!
ok

3、UDP服务器

UDP服务器建立与TCP相类似,具体比较如下:

步骤 UDP TCP
第一步 建立socket对象 建立socket对象
第二步 设置socket选项 设置socket选项
第三步 绑定到一个端口 绑定到一个端口
第四步 Recvfrom() 侦听连接listen

这里利用UDP建立一个时间服务器。

代码如下:

服务器端;serverudp.py

# -*- coding: cp936 -*-
##UDP服务器端,客户端连接后,向其发送当前时间
##@小五义 
import socket,traceback,time,struct
host=''
port=12345
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind((host,port))
while 1:
    try:
        message,address=s.recvfrom(8192)
        secs=int(time.time())
        reply=struct.pack("!I",secs)
        s.sendto(reply,address)
    except (KeyboardInterrupt,SystemExit):
        raise
    except:
        traceback.print_exc()

客户端:clientudp.py

# -*- coding: cp936 -*-
##udp客户端,向服务器发送一个空字符后,得到服务器返回时间
##@小五义 
import socket,sys,struct,time
host=raw_input('输入服务器地址:')
port=12345
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.sendto('',(host,port))
print "等待回复……"
buf=s.recvfrom(2048)[0]
if len(buf)!=4:
    print "回复错误%d:%s"%(len(buf),buf)
    sys.exit(1)
secs=struct.unpack("!I",buf)[0]
print time.ctime(int(secs))

运行结果:

首先运行服务器端,然后运行客户端。
C:\>python clientudp.py  ##clientudp.py程序存放在在c盘下
输入服务器地址:127.0.0.1
等待回复……
Mon Aug 06 17:09:17 2012

Python 相关文章推荐
python使用PIL模块实现给图片打水印的方法
May 22 Python
python妹子图简单爬虫实例
Jul 07 Python
Python中数字以及算数运算符的相关使用
Oct 12 Python
简单讲解Python中的数字类型及基本的数学计算
Mar 11 Python
python生成不重复随机数和对list乱序的解决方法
Apr 09 Python
对python list 遍历删除的正确方法详解
Jun 29 Python
Python中pandas dataframe删除一行或一列:drop函数详解
Jul 03 Python
python 自定义对象的打印方法
Jan 12 Python
使用Python做定时任务及时了解互联网动态
May 15 Python
Python实现Mysql数据统计及numpy统计函数
Jul 15 Python
python垃圾回收机制(GC)原理解析
Dec 30 Python
Python实现智慧校园自动评教全新版
Jun 18 Python
python网络编程学习笔记(二):socket建立网络客户端
Jun 09 #Python
python网络编程学习笔记(一)
Jun 09 #Python
有关wxpython pyqt内存占用问题分析
Jun 09 #Python
wxpython 最小化到托盘与欢迎图片的实现方法
Jun 09 #Python
Python实例之wxpython中Frame使用方法
Jun 09 #Python
wxpython学习笔记(推荐查看)
Jun 09 #Python
wxPython中文教程入门实例
Jun 09 #Python
You might like
回首过去10年中最搞笑的10部动漫,哪一部让你节操尽碎?
2020/03/03 日漫
php $_SERVER["REQUEST_URI"]获取值的通用解决方法
2010/06/21 PHP
一些php技巧与注意事项分析
2011/02/03 PHP
php生成局部唯一识别码LUID的代码
2012/10/06 PHP
Codeigniter出现错误提示Error with CACHE directory的解决方案
2014/06/12 PHP
PHP实现的简单网络硬盘
2015/07/29 PHP
php+ajax 实现输入读取数据库显示匹配信息
2015/10/08 PHP
PHP+RabbitMQ实现消息队列的完整代码
2019/03/20 PHP
JS去除数组重复值的五种不同方法
2013/09/06 Javascript
jquery中ajax跨域方法实例分析
2015/12/18 Javascript
javascript执行环境及作用域详解
2016/05/05 Javascript
谈一谈bootstrap响应式布局
2016/05/23 Javascript
JS中常用的正则表达式
2016/09/29 Javascript
JavaScript中的await/async的作用和用法
2016/10/31 Javascript
JS弹出窗口的运用与技巧大全
2016/11/01 Javascript
vue2滚动条加载更多数据实现代码
2017/01/10 Javascript
javascript数组拍平方法总结
2018/01/20 Javascript
关于jquery中attr()和prop()方法的区别
2018/05/28 jQuery
Vue2.5学习笔记之如何在项目中使用和配置Vue
2018/09/26 Javascript
koa2服务端使用jwt进行鉴权及路由权限分发的流程分析
2019/07/22 Javascript
[02:44]2014DOTA2 国际邀请赛中国区预选赛 大神红毯秀
2014/05/25 DOTA
web.py获取上传文件名的正确方法
2014/08/26 Python
使用Python实现BT种子和磁力链接的相互转换
2015/11/09 Python
解析Python中的eval()、exec()及其相关函数
2017/12/20 Python
用TensorFlow实现戴明回归算法的示例
2018/05/02 Python
numpy中的delete删除数组整行和整列的实例
2018/05/09 Python
详解重置Django migration的常见方式
2019/02/15 Python
python scrapy爬虫代码及填坑
2019/08/12 Python
自定义django admin model表单提交的例子
2019/08/23 Python
python在不同条件下的输入与输出
2020/02/13 Python
彻底搞懂 python 中文乱码问题(深入分析)
2020/02/28 Python
Python读入mnist二进制图像文件并显示实例
2020/04/24 Python
Jogun Shop中文官网:韩国知名时尚男装网站
2016/10/12 全球购物
母亲80寿诞答谢词
2014/01/16 职场文书
教师自我鉴定范文
2014/03/20 职场文书
opencv-python图像配准(匹配和叠加)的实现
2021/06/23 Python