#!/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)