Python的套接字、IPv4和简单的客户端/服务器编程
2017-03-18 22:28
344 查看
#!/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网络编程攻略》
相关文章推荐
- 套接字、IPv4和简单的客户端/服务器编程
- Python——简单的TCP & UDP 服务器 和 相应的客户端编程
- 《Python网络编程》Part1 Socket、IPv4和简单的客户端/服务器编程
- 2015-05-06python-web攻略(1)套接字-IPv4-简单的客户端服务器编程
- Python 网络编程---简单的服务器与客户端实现---阻塞式编写
- Python网络编程 3.1 由简单的TCP服务器、客户端程序分析相关方法
- Linux socket编程-最简单的服务器和客户端程序
- Linux 网络编程基础(一) ---------------客户端/服务器的简单实现
- 用python的twisted做个简单游戏服务器原形--客户端连接monitor管理类
- 流式套接字客户端/服务器编程
- 用python的twisted做个简单游戏服务器原形--客户端逻辑ClientService类
- android的Socket编程---实现简单的服务器,并与客户端通信
- Linux 网络编程基础 客户端/服务器的简单实现
- Windows Socket 编程_ 简单的服务器/客户端程序 .
- Linux 网络编程基础(一) ---------------客户端/服务器的简单实现
- 流式套接字客户端/服务器编程
- socket编程:服务器与客户端简单交互的例子
- Linux 网络编程基础(一) ---------------客户端/服务器的简单实现
- 简单的python流回显服务器与客户端(二)
- Linux socket编程-最简单的服务器和客户端程序