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中关于for循环的碎碎念
Jun 30 Python
Java及python正则表达式详解
Dec 27 Python
Python爬虫文件下载图文教程
Dec 23 Python
windows10下安装TensorFlow Object Detection API的步骤
Jun 13 Python
PyQt5 在label显示的图片中绘制矩形的方法
Jun 17 Python
python过滤中英文标点符号的实例代码
Jul 15 Python
Python中的延迟绑定原理详解
Oct 11 Python
Python对Tornado请求与响应的数据处理
Feb 12 Python
浅谈keras2 predict和fit_generator的坑
Jun 17 Python
Python如何优雅删除字符列表空字符及None元素
Jun 25 Python
关于PySnooper 永远不要使用print进行调试的问题
Mar 04 Python
Python爬虫实战之爬取携程评论
Jun 02 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
用cookies来跟踪识别用户
2006/10/09 PHP
php strcmp使用说明
2010/04/22 PHP
php function用法如何递归及return和echo区别
2014/03/07 PHP
PHP基于SPL实现的迭代器模式示例
2018/04/22 PHP
PHP 中 var_export、print_r、var_dump 调试中的区别
2018/06/19 PHP
php ajax数据传输和响应方法
2018/08/21 PHP
JScript内置对象Array中元素的删除方法
2007/03/08 Javascript
jQuery-Tools-overlay 使用介绍
2012/07/14 Javascript
JavaScript 产生不重复的随机数三种实现思路
2012/12/13 Javascript
Nodejs实战心得之eventproxy模块控制并发
2015/10/27 NodeJs
关于backbone url请求中参数带有中文存入数据库是乱码的快速解决办法
2016/06/13 Javascript
jQuery EasyUI 右键菜单--关闭标签/选项卡的简单实例
2016/10/10 Javascript
浅谈js键盘事件全面控制
2016/12/01 Javascript
vue中component组件的props使用详解
2017/09/04 Javascript
VUE实现一个分页组件的示例
2017/09/13 Javascript
微信小程序wx.getImageInfo()如何获取图片信息
2018/01/26 Javascript
解决vue 更改计算属性后select选中值不更改的问题
2018/03/02 Javascript
如何使用 vue + d3 画一棵树
2018/12/03 Javascript
vue2.0+SVG实现音乐播放圆形进度条组件
2019/09/21 Javascript
element 中 el-menu 组件的无限极循环思路代码详解
2020/04/26 Javascript
js屏蔽F12审查元素,禁止修改页面代码等实现代码
2020/10/02 Javascript
基于vue的video播放器的实现示例
2021/02/19 Vue.js
[38:41]2014 DOTA2国际邀请赛中国区预选赛 LGD VS CNB
2014/05/22 DOTA
Python中为什么要用self探讨
2015/04/14 Python
Django开发中的日志输出的方法
2018/07/02 Python
sublime3之内网安装python插件Anaconda的流程
2020/11/10 Python
python中xlutils库用法浅析
2020/12/29 Python
法国太阳镜店:Sunglasses Shop
2016/08/27 全球购物
e路東瀛(JAPANiCAN)香港:日本旅游、日本酒店和温泉旅馆预订
2018/11/21 全球购物
C#中有没有静态构造函数,如果有是做什么用的?
2016/06/04 面试题
一些Unix笔试题和面试题
2013/01/22 面试题
毕业生个人求职的自我评价
2013/10/28 职场文书
生产部主管岗位职责
2014/01/06 职场文书
武夷山导游词
2015/02/03 职场文书
信仰纪录片观后感
2015/06/08 职场文书
寻找最美乡村教师观后感
2015/06/18 职场文书