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实现颜色空间转换程序(Tkinter)
Dec 31 Python
Python进阶_关于命名空间与作用域(详解)
May 29 Python
浅谈python迭代器
Nov 08 Python
python3利用venv配置虚拟环境及过程中的小问题小结
Aug 01 Python
解决python 自动安装缺少模块的问题
Oct 22 Python
python3 property装饰器实现原理与用法示例
May 15 Python
对python特殊函数 __call__()的使用详解
Jul 02 Python
python树的同构学习笔记
Sep 14 Python
Python中使用socks5设置全局代理的方法示例
Apr 15 Python
使用Numpy对特征中的异常值进行替换及条件替换方式
Jun 08 Python
使用numpy实现矩阵的翻转(flip)与旋转
Jun 03 Python
OpenCV图像变换之傅里叶变换的一些应用
Jul 26 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
php+mysql开源XNA 聚合程序发布 下载
2007/07/13 PHP
PHP下操作Linux消息队列完成进程间通信的方法
2010/07/24 PHP
linux命令之调试工具strace的深入分析
2013/06/03 PHP
测试php函数的方法
2013/11/13 PHP
PHP抓屏函数实现屏幕快照代码分享
2014/01/02 PHP
PHP+JQuery+Ajax实现分页方法详解
2016/08/06 PHP
PHP实现数组向任意位置插入,删除,替换数据操作示例
2019/04/05 PHP
某页码显示的helper 少量调整,另附js版
2010/09/12 Javascript
JavaScript地理位置信息API
2016/06/11 Javascript
基于原生JS实现图片裁剪
2016/08/01 Javascript
jQuery实现带遮罩层效果的blockUI弹出层示例【附demo源码下载】
2016/09/14 Javascript
Reactjs实现通用分页组件的实例代码
2017/01/19 Javascript
原生javascript移动端滑动banner效果
2017/03/10 Javascript
vue-router 中router-view不能渲染的解决方法
2017/05/23 Javascript
node.js中fs文件系统目录操作与文件信息操作
2018/02/24 Javascript
修改vue源码实现动态路由缓存的方法
2020/01/21 Javascript
Jquery使用each函数实现遍历及数组处理
2020/07/14 jQuery
Python环境下安装使用异步任务队列包Celery的基础教程
2016/05/07 Python
Python探索之自定义实现线程池
2017/10/27 Python
Python编程之基于概率论的分类方法:朴素贝叶斯
2017/11/11 Python
Windows 7下Python Web环境搭建图文教程
2018/03/20 Python
[原创]Python入门教程1. 基本运算【四则运算、变量、math模块等】
2018/10/28 Python
在python中对变量判断是否为None的三种方法总结
2019/01/23 Python
Python绘制热力图示例
2019/09/27 Python
Python操作SQLite/MySQL/LMDB数据库的方法
2019/11/07 Python
Python模块相关知识点小结
2020/03/09 Python
python邮件中附加文字、html、图片、附件实现方法
2021/01/04 Python
英国在线潜水商店:Simply Scuba
2019/03/25 全球购物
远程调用的原理
2014/07/05 面试题
旅游管理毕业生自荐信
2013/11/05 职场文书
职工趣味运动会方案
2014/02/10 职场文书
公司成本主管岗位责任制
2014/02/21 职场文书
音乐教师个人总结
2015/02/06 职场文书
房屋转让协议书(标准范本)
2016/03/21 职场文书
SQL Server——索引+基于单表的数据插入与简单查询【1】
2021/04/05 SQL Server
python游戏开发Pygame框架
2022/04/22 Python