#!/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
" % 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("
")
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 * ' '
# 将数据发送给服务器
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 ' Time=%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网络编程攻略》