Python的套接字、IPv4和简单的客户端/服务器编程
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
from binascii import hexlify
import sys
# 对用户输入的命令行参数进行解析
import argparse
# 先$ pip install ntplib 安装需要的python库文件
import ntplib
from time import ctime
import struct
# python中每个函数之间要隔2行
# 发送数据缓冲区的大小
SEND_BUF_SIZE = 4096
# 接受数据缓冲区的大小
RECV_BUF_SIZE = 4096
NTP_SERVER = "0.uk.pool.ntp.org"
TIME1970 = 2208988800L
def print_local_machine_infor():
"""打印本地主机名和本地主机的ip地址"""
host_name = socket.gethostname()
host_ip_address = socket.gethostbyname(host_name)
print "Host name: %s" % host_name
print "Host ip address: %s" % host_ip_address
def get_remote_machine_infor(remote_host_name="www.python.org"):
"""获取远程服务器的ip地址"""
try:
print "Remote ip address: %s" % socket.gethostbyname(remote_host_name)
except socket.error, err_msg:
print "%s: %s" % (remote_host_name, err_msg)
def convert_ip4_address(ip_address):
# 将一个字符串IP地址转换为一个32位的网络字节序列(ascii码转二进制)
packed_ip_address = socket.inet_aton(ip_address)
# 将32位网络字节序列转换成字符串形式的ip地址(二进制转ascii码)
unpacked_ip_address = socket.inet_ntoa(packed_ip_address)
# 将二进制数据的网络字节序列hexlify转换成16进制显示
print "Ip Address: %s => Packed: %s, Unpacked: %s" \
% (ip_address, hexlify(packed_ip_address), unpacked_ip_address)
def find_service_name(protocol_name, port_number):
"""根据网络协议和端口号,获取服务名称"""
print "Port: %s => service name: %s" % (port_number, socket.getservbyport(port_number, protocol_name))
def convert_integer(port_number):
"""网络端口之间序列的转换"""
# 32-bit--将数据从网络字节序和主机字节序之间进行转换
print "Original: %s => Long host byte order: %s, Network byte order: %s" \
% (port_number, socket.ntohl(port_number), socket.htonl(port_number))
# 16-bit--将数据从网络字节序和主机字节序之间进行转换
print "Original: %s => Short host byte order: %s, Network byte order: %s" \
% (port_number, socket.ntohs(port_number), socket.htons(port_number))
def set_tcp_socket_timeout(wait_time):
"""设置tcp套接字的超时等待时间"""
# 创建流式tcp套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 打印套接字的默认的超时等待时间
print "Default socket timeout: %s" % s.gettimeout()
# 设置套接字的超时等待时间
s.settimeout(wait_time)
print "Current socket timeout: %s" % s.gettimeout()
def send_data_to_server():
# 构建命令行参数解释器
parser = argparse.ArgumentParser(description='Socket Error Examples')
# 添加命令行的可选输入参数
parser.add_argument('--host', action="store", dest="host", required=False)
parser.add_argument('--port', action="store", dest="port", type=int, required=False)
parser.add_argument('--file', action="store", dest="file", required=False)
# 替换输入手动输入的命令行
given_args = parser.parse_args(["--host=www.python.org", "--port=80", "--file=Hello World"])
# 获取命令行输入的主机名
host = given_args.host
# 获取命令行输入的端口号
port = given_args.port
# 获取命令行输入的发送数据
filename = given_args.file
# 创建tcp网络套接字
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, e:
# 打印创建网络套接字的错误
print "Error creating socket: %s" % e
# 退出进程
sys.exit(1)
# 向指定的网络服务器发起网络连接
try:
s.connect((host, port))
except socket.gaierror, e:
print "Address-related error connecting to server: %s" % e
sys.exit(1)
except socket.error, e:
print "Connection error: %s" % e
sys.exit(1)
try:
# 向指定的服务器发送数据请求
s.sendall("GET %s HTTP/1.0\r\n\r\n" % filename)
except socket.error, e:
print "Error sending data: %s" % e
sys.exit(1)
# 循环输入服务器返回的数据
while 1:
# 接受请求服务器返回的数据
try:
buf = s.recv(2048)
except socket.error, e:
print "Error receiving data: %s" % e
sys.exit(1)
# 判断服务器返回的数据是否为null
if not len(buf):
break
# 将指定服务器返回的数据打印出来
sys.stdout.write(buf)
# 换行
sys.stdout.write("\r\n")
def modify_buff_size():
# 创建流式tcp套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 获取套接字默认发送数据缓冲区的大小
bufsize = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
print "Orig Send Buffer size [Before]:%d" % bufsize
bufsize = sock.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)
print "Orig Recv Buffer size [Before]:%d" % bufsize
# 设置网络套接字为非延迟模式
sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
# 设置网络套接字的发送数据缓冲区的大小
sock.setsockopt(
socket.SOL_SOCKET,
socket.SO_SNDBUF,
SEND_BUF_SIZE)
# 设置网络套接字的接受数据缓冲区的大小
sock.setsockopt(
socket.SOL_SOCKET,
socket.SO_RCVBUF,
RECV_BUF_SIZE)
# 打印设置以后的网络套接字的发送数据缓冲区的大小
bufsize = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
print "Send Buffer size [After]:%d" % bufsize
# 打印设置以后的网络套接字的接受数据缓冲区的大小
bufsize = sock.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)
print "Recv Buffer size [After]:%d" % bufsize
def reuse_socket_addr():
# 创建tcp流式套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 获取网络套接字默认的地址重用状态值
old_state = sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
print "Old sock state: %s" % old_state
# 设置网络套接字的地址重用状态的值为1即重用套接字地址
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 获取网络套接字的地址新的重用状态值
new_state = sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
print "New sock state: %s" % new_state
# 端口
local_port = 8282
# 创建新的套接字
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置网络套接字的地址为可重用的
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定网络套接字
srv.bind(("127.0.0.1", local_port))
# 进行网络套接字的监听
srv.listen(1)
print ("Listening on port: %s " % local_port)
while True:
# 接受客户端的网络连接
try:
connection, addr = srv.accept()
print 'Connected by %s:%s' % (addr[0], addr[1])
except KeyboardInterrupt:
break
except socket.error, msg:
print '%s' % (msg,)
def test_socket_modes():
# 创建tcp网络套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置网络模式为阻塞模式
s.setblocking(1)
# 设置超时等待时间
s.settimeout(0.5)
# 绑定ip地址和端口号
s.bind(("127.0.0.1", 0))
# 获取网路套接字的信息("ip地址", 端口号)
socket_address = s.getsockname()
# 打印网络套接字的名称
print "Trivial Server lauched on socket: %s" % str(socket_address)
# 进行网络套接字的监听,等待客户端的连接
while 1:
s.listen(1)
def print_ntp_time():
# 创建NTPClient实例对象
ntp_client = ntplib.NTPClient()
# 向NTP服务器发送时间请求
response = ntp_client.request('pool.ntp.org')
# 打印获取的时间
print "ntp time: "+str(ctime(response.tx_time))
def sntp_client():
# 创建udp套接字
client = socket.socket( socket.AF_INET, socket.SOCK_DGRAM)
# 构建发送的数据包
data = '\x1b' + 47 * '\0'
# 将数据发送给服务器
client.sendto(data, (NTP_SERVER, 123))
# 获取服务返回的数据和ip地址(元组)
data, address = client.recvfrom(1024)
if data:
print 'Response received from:', address
# 解包服务返回的数据即时间
t = struct.unpack('!12I', data)[10]
# 减去从1970年1月1日对应的时间戳
t -= TIME1970
# 打印获取到的时间信息
print '\tTime=%s' % ctime(t)
# 若当前模块,直接执行时,执行下面的代码
if __name__ == '__main__':
# 打印本地主机的名称和ip地址
print_local_machine_infor()
# 获取远程服务器的ip地址
get_remote_machine_infor()
# 进行ip地址的转换
convert_ip4_address("192.168.0.1")
# 通过端口号和协议,获取服务名称
for obj in [("tcp", 80), ("tcp", 25), ("tcp", 53)]:
find_service_name(obj[0], obj[1])
# 网络端口的字节序的转换
convert_integer(80)
# 设置tcp套接字的超时等待时间
set_tcp_socket_timeout(10)
# 向指定的服务发送数据
send_data_to_server()
# 修改网路套接字的接受数据和发送数据的缓冲区的大小
modify_buff_size()
# 打印ntp网络时间
print_ntp_time()
# 获取当前时间
sntp_client()
# 创建阻塞模式的服务器套接字
#test_socket_modes()
# 重用套接字地址
reuse_socket_addr()
简单的网路连接服务端
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import argparse
host = 'localhost'
data_payload = 2048
backlog = 5
def echo_server(port):
""" 简单的网络连接服务器 """
# 创建流式TCP网络套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 设置可以重用网络套接字地址
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 构建绑定网络套接字的信息对象
server_address = (host, port)
print "Starting up echo server on %s port %s" % server_address
# 绑定ip地址和端口
sock.bind(server_address)
# 进行网络套接字的监听
sock.listen(backlog)
while True:
print "Waiting to receive message from client"
# 接受客户端的网络连接
client, address = sock.accept()
# 接受客户端发送来的数据
data = client.recv(data_payload)
# 向客户端发送数据
if data:
print "Data: %s" % data
client.send(data)
print "sent %s bytes back to %s" % (data, address)
# 关闭网络套接字
client.close()
if __name__ == '__main__':
# 构建命令行参数解释器
parser = argparse.ArgumentParser(description='Socket Server Example')
# 添加非可选参数--port(端口号)
parser.add_argument('--port', action="store", dest="port", type=int, required=False)
# 解析用户输入的命令行参数
given_args = parser.parse_args(["--port=8777"])
# 获取网络连接的端口号
port = given_args.port
# 创建网络连接的服务器
echo_server(port)
简单的网络连接客户端
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import argparse
host = 'localhost'
def echo_client(port):
""" 简单网络连接客户端 """
# 创建TCP流式网络套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 构建连接服务器的信息对象(ip地址,端口号)
server_address = (host, port)
print "Connecting to %s port %s" % server_address
# 向服务器发起网络连接
sock.connect(server_address)
try:
# 发送给服务器的数据
message = "Test message. This will be echoed"
print "Sending %s" % message
# 向服务器发送数据信息
sock.sendall(message)
amount_received = 0
# 期望收到服务器返回的数据长度
amount_expected = len(message)
# 循环获取服务器返回给客户端的数据
while amount_received < amount_expected:
# 获取服务器返回的数据
data = sock.recv(16)
amount_received += len(data)
print "Received: %s" % data
except socket.errno, e:
print "Socket error: %s" % str(e)
except Exception, e:
print "Other exception: %s" % str(e)
finally:
print "Closing connection to the server"
# 关闭网络套接字
sock.close()
if __name__ == '__main__':
# 构建命令行参数解释器对象
parser = argparse.ArgumentParser(description='Socket Server Example')
# 添加非可选的参数--port(端口号)
parser.add_argument('--port', action="store", dest="port", type=int, required=False)
# 解析用户输入的命令行参数
given_args = parser.parse_args(["--port=8777"])
# 获取用户输入的网络端口号
port = given_args.port
# 创建网络连接客户端
echo_client(port)
参考:《python网络编程攻略》
Python的套接字、IPv4和简单的客户端/服务器编程的更多相关文章
- Python之套接字
Python之套接字 客户端Client/服务端Server架构: 1.硬件C/S架构 2.软件C/S架构 OSI4层:4层里有五层,五层里又有7层. 四层---------五层--------七层 ...
- Python Socket套接字编程
Python 的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.Py ...
- Python原始套接字编程
在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM进行发送数据包,需要进行完整的TCP交互. 因此想使用原始套接字进行编程,直接构造数据包,并在IP层进行发送,即采用SOCK_R ...
- python socket 套接字编程 单进程服务器 实现多客户端访问
服务器: import socket #单进程服务器 实现多客户端访问 IO复用 #吧所有的客户端套接字 放在一个列表里面,一次又一次的便利过滤 server = socket.socket(sock ...
- python UDP套接字通信
UDPserver.py import socket #导入套接字模块 s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # - socket.A ...
- Python原始套接字编程-乾颐堂
在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM进行发送数据包,需要进行完整的TCP交互. 因此想使用原始套接字进行编程,直接构造数据包,并在IP层进行发送,即采用SOCK_R ...
- Python Socket套接字
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Un ...
- Python socket套接字通信
一.什么是socket? socket是一个模块, 又称套接字,用来封装 互联网协议(应用层以下的层). 二.为什么要有socket? socket可以实现互联网协议 应用层以下的层 的工作,提高开发 ...
- 基于TCP套接字实现的简单Demo
由于代码的注释已经很详尽了,所以这里不再作过多说明.仅仅贴出代码和结果图. 值得注意的是必须先启动server程序再启动client. Server: #include <WINSOCK2.H& ...
随机推荐
- 剑指 Offer 13. 机器人的运动范围 + 深搜 + 递归
剑指 Offer 13. 机器人的运动范围 题目链接 package com.walegarrett.offer; /** * @Author WaleGarrett * @Date 2020/12/ ...
- ACM STU week3
STU ACM训练week3(2.5-2.15) By@Xiezeju 训练计划的CP4配套资源库 训练时间安排 定期任务 任务 每日 进行1小时的盲打训练锻练手速 打字网站,最好注册账号以保存进度 ...
- MySQL全面瓦解24:构建高性能索引(策略篇)
学习如果构建高性能的索引之前,我们先来了解下之前的知识,以下两篇是基础原理,了解之后,对面后续索引构建的原则和优化方法会有更清晰的理解: MySQL全面瓦解22:索引的介绍和原理分析 MySQL全面瓦 ...
- [SDOI2009] HH的项链(待续)
[SDOI2009] HH的项链(待续) 题目大意:对一个由若干个数字(可重复)组成的数列,询问\([l,r]\)中出现的不同的数字数量 考试时(考试时范围小)用的暴力,but,没有考虑数字0的情况, ...
- SHA算法摘要处理
byte[] input="sha".getBytes();//待做消息摘要算法的原始信息,可以是任意字符串 MessageDigest sha=MessageDigest.get ...
- 前端性能监控之performance
如果我们想要对一个网页进行性能监控,那么使用window.performance是一个比较好的选择. 我们通过window.performance可以获取到用户访问一个页面的每个阶段的精确时间,从而对 ...
- Hznu_oj 2340 你敢一个人过桥吗?
Description 在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边.如果不借助手电筒的话,大家是无论如何也不敢过桥去的.不幸的是,N个人一共只带了一只手电筒,而桥窄得只够让两个人同时过. ...
- go中semaphore(信号量)源码解读
运行时信号量机制 semaphore 前言 作用是什么 几个主要的方法 如何实现 sudog 缓存 acquireSudog releaseSudog semaphore poll_runtime_S ...
- DAOS 分布式异步对象存储|数据平面
DAOS 通过两个紧密集成的平面进行运转.数据平面处理繁重的运输操作,而控制平面负责进程编排和存储管理,简化数据平面的操作. 模块接口 I/O 引擎支持一个模块接口,该接口允许按需加载服务器端代码.每 ...
- [贪心]D. 【例题4】国王游戏
D . [ 例 题 4 ] 国 王 游 戏 D. [例题4]国王游戏 D.[例题4]国王游戏 解析 贪心思想,考虑交换后的值比交换前的小. 然后数据规模用高精度 Code #include <b ...