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备份文件以及mysql数据库的脚本代码
Jun 10 Python
跟老齐学Python之重回函数
Oct 10 Python
Python打印scrapy蜘蛛抓取树结构的方法
Apr 08 Python
python使用socket远程连接错误处理方法
Apr 29 Python
python3实现字符串操作的实例代码
Apr 16 Python
在python中实现调用可执行文件.exe的3种方法
Jul 07 Python
在Django的View中使用asyncio的方法
Jul 12 Python
如何通过python的fabric包完成代码上传部署
Jul 29 Python
Python多线程及其基本使用方法实例分析
Oct 29 Python
Python使用PyQt5/PySide2编写一个极简的音乐播放器功能
Feb 07 Python
Python读入mnist二进制图像文件并显示实例
Apr 24 Python
python批量生成条形码的示例
Oct 10 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的特殊设置
2006/10/09 PHP
php MsSql server时遇到的中文编码问题
2009/06/11 PHP
thinkphp的静态缓存用法分析
2014/11/29 PHP
PHP实现获取文件后缀名的几种常用方法
2015/08/08 PHP
Thinkphp3.2.3分页使用实例解析
2016/07/28 PHP
javascript显示隐藏层比较不错的方法分析
2008/09/30 Javascript
仿jQuery的siblings效果的js代码
2011/08/09 Javascript
jQuery实现鼠标滑过遮罩并高亮显示效果
2013/07/16 Javascript
给事件响应函数传参数的四种方式小结
2013/12/05 Javascript
Jquery性能优化详解
2014/05/15 Javascript
JavaScript中的6种运算符总结
2014/10/16 Javascript
jquery.uploadify插件在chrome浏览器频繁崩溃解决方法
2015/03/01 Javascript
详解addEventListener的三个参数之useCapture
2015/03/16 Javascript
JavaScript自定义文本框光标
2017/03/05 Javascript
vue+element-ui+ajax实现一个表格的实例
2018/03/09 Javascript
解决vue-cli单页面手机应用input点击手机端虚拟键盘弹出盖住input问题
2018/08/25 Javascript
bootstrap table合并行数据并居中对齐效果
2018/10/17 Javascript
qrcode生成二维码微信长按无法识别问题的解决
2019/04/04 Javascript
微信公众号平台接口开发 菜单管理的实现
2019/08/14 Javascript
jquery实现淡入淡出轮播图效果
2020/12/13 jQuery
Vue实现小购物车功能
2020/12/21 Vue.js
python使用7z解压软件备份文件脚本分享
2014/02/21 Python
使用Python获取Linux系统的各种信息
2014/07/10 Python
python在非root权限下的安装方法
2018/01/23 Python
pandas数据清洗,排序,索引设置,数据选取方法
2018/05/18 Python
python 制作自定义包并安装到系统目录的方法
2018/10/27 Python
pyenv虚拟环境管理python多版本和软件库的方法
2019/12/26 Python
Selenium 滚动页面至元素可见的方法
2020/03/18 Python
Java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类
2012/02/06 面试题
初中三年学生的学习自我评价
2013/11/13 职场文书
写给女朋友的检讨书
2014/01/28 职场文书
中国世界遗产导游词
2015/02/13 职场文书
电影焦裕禄观后感
2015/06/09 职场文书
2019假期福利管理制度!
2019/07/15 职场文书
写作技巧:优秀文案必备的3种结构
2019/08/19 职场文书
Nginx虚拟主机的配置步骤过程全解
2022/03/31 Servers