python的socket编程
Posted akiz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python的socket编程相关的知识,希望对你有一定的参考价值。
socket
Socket是网络编程的一个抽象概念。通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可。
socket参数
socket地址族
socket.``AF_UNIX unix本机进程间通信
socket.``AF_INET ipv4
socket.``AF_INET6 ipv6
socket类型
socket.``SOCK_STREAM TCP
socket.``SOCK_DGRAM UDP
socket.``SOCK_RAW #原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
socket.``SOCK_RDM #是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
socket.``SOCK_SEQPACKET #不使用了
socket方法
socket.
socket`(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)
socket.``accept
()?
socket.``bind
(address)?
socket.``close
()?
socket.``getblocking
()?
socket.``setblocking
(flag)?
socket.``listen
([backlog])?
socket.``send
(bytes[, flags])?
socket.``sendall
(bytes[, flags])?
socket.``sendto
(bytes, address)?
socket.``sendto
(bytes, flags, address)
socket.``recv
(bufsize[, flags])?
socket.``recvfrom
(bufsize[, flags]))?
TCP编程
TCP客户端和服务器端的交互过程
==注意:3.7.3测试多个TCP客户端,当客户端非正常断开,服务器程序也会崩掉==
例子1:简单的ssh的socket服务器客户端
有几个问题需要注意的:
- 问题1:socket每次接收和发送都有最大数据量限制的,发送的数据最大量的限制 就是缓冲区能缓存的数据的最大量。
- 问题2:粘包问题,即服务器端你调用时send 2次,但你send调用时,数据其实并没有立刻被发送给客户端,而是放到了系统的socket发送缓冲区里,等缓冲区满了、或者数据等待超时了,数据才会被send到客户端,这样就把好几次的小数据拼成一个大数据,统一发送到客户端了,这么做的目地是为了提高io利用效率,一次性发送总比连发好几次效率高嘛。 但也带来一个问题,就是“粘包”,即2次或多次的数据粘在了一起统一发送了。
- 解决办法:
- 1.服务器发送数据包的大小,再发送数据包,客户端根据数据包的大小判断数据是否完全接收
- 2.两次send出现的粘包问题
- 方法1,time.sleep(0.5)秒,缓存区超时,就会把数据发送给客户端(不建议)
- 方法2,在两次send之间,服务器设置一个rev,客户端设置一个send。在客户端不发送确认报文。服务器端不会主动的发送第2次的sendall数据,从而达到两次send的数据隔开。
#客户端
import socket
if __name__ == '__main__':
server_ip = "localhost"
server_port = 9999
client = socket.socket()
client.connect((server_ip, server_port))
while True:
msg = input(">>:").strip()
if not msg:
continue
client.send(msg.encode('utf-8'))
res_recv_size = client.recv(1024).decode()
client.send("ACK应答".encode("utf-8"))
total_res_size = int(res_recv_size)
print("收到指令结果的大小:%s" % total_res_size)
recv_res_size = 0
cmd_res = b''
while recv_res_size != total_res_size:
data = client.recv(1024)
recv_res_size += len(data)
cmd_res += data
print(recv_res_size)
else:
print("数据收完了!!")
print(cmd_res.decode())
client.close()
#服务器端
import socket
import os
if __name__ == '__main__':
server = socket.socket()
server.setblocking(True)
server.bind(("localhost", 9999))
server.listen(5)
while True:
print("等待新连接。。。")
conn, addr = server.accept()
print("新连接接入", addr)
while True:
data = conn.recv(1024)
if not data:
print("客户端断开连接")
break
print("收到数据%s" % data)
res = os.popen(data.decode()).read()
if len(res):
conn.send(str(len(res)).encode('utf-8'))
print("等待客户ack应答...")
client_final_ack = conn.recv(1024) # 等待客户端响应
print("客户应答:", client_final_ack.decode())
conn.sendall(res.encode("utf-8"))
else:
conn.send(b"command error")
server.close()
UDP编程
#服务器端
import socket
if __name__ == '__main__':
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(("localhost", 9999))
data, addr = server.recvfrom(1024)
print("收到数据:", data.decode())
print("发送人:", addr)
server.sendto(data, addr)
server.close()
#客户端
import socket
if __name__ == '__main__':
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
data = b'hello world'
HOST, PORT = "localhost", 9999
client.sendto(data, (HOST, PORT))
data, addr = client.recvfrom(1024)
print(data.decode(), addr)
client.close()
socketserver
socketserver
— A framework for network servers?
同步
class
socketserver.``TCPServer
(server_address, RequestHandlerClass, bind_and_activate=True)This uses the Internet TCP protocol, which provides for continuous streams of data between the client and server. If bind_and_activate is true, the constructor automatically attempts to invoke
server_bind()
andserver_activate()
. The other parameters are passed to theBaseServer
base class.class
socketserver.``UDPServer
(server_address, RequestHandlerClass, bind_and_activate=True)This uses datagrams, which are discrete packets of information that may arrive out of order or be lost while in transit. The parameters are the same as for
TCPServer
.class
socketserver.``UnixStreamServer
(server_address, RequestHandlerClass, bind_and_activate=True)class
socketserver.``UnixDatagramServer
(server_address, RequestHandlerClass, bind_and_activate=True)These more infrequently used classes are similar to the TCP and UDP classes, but use Unix domain sockets; they’re not available on non-Unix platforms. The parameters are the same as for
TCPServer
.
异步
- class
socketserver.``ForkingTCPServer
? - class
socketserver.``ForkingUDPServer
? - class
socketserver.``ThreadingTCPServer
? - class
socketserver.``ThreadingUDPServer
?
简单TCP的sockeserver
#服务器端
import socketserver
class Myhandle(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).decode()
print(self.data)
self.request.sendall(self.data.upper().encode("utf-8"))
if __name__ == '__main__':
HOST, PORT = "localhost", 9999
server = socketserver.TCPServer((HOST, PORT), Myhandle) #单线程
# server = socketserver.ThreadingTCPServer((HOST, PORT), Myhandle) #多线程
server.serve_forever()
#客户端
import socket
if __name__ == '__main__':
server_ip = "localhost"
server_port = 9999
client = socket.socket()
client.connect((server_ip, server_port))
while True:
msg = input(">>:").strip()
if not msg:
continue
client.send(msg.encode('utf-8'))
data = client.recv(1024)
print(data.decode())
client.close()
以上是关于python的socket编程的主要内容,如果未能解决你的问题,请参考以下文章