python网络编程(一)
之前学习过一些python的socket编程和requests库,时间一久,就容易生疏和遗忘,后面我想要学习pwntools的源码,封装的tube模块的函数,一定也是通过套接字来进行通信的。
最近复习一波,加深印象,温故而知新。
一.socket函数
socket库,用socket()函数来建立套接字,实现服务器与服务器之间的通信。
socket.socket([family[,type[,proto] ] ])
socket函数有三个参数,分别如下:
family:套接字家族可以使用AF_UNIX或者AF_INET,AF_UNIX函数用于同一台机器上的进程通信(即本机通信),AF_INET可以实现不同服务器之间的通信。
type:套接字类型可以依据是面向连接还是非连接SOCK_STREAM或SOCK_DGRAM。SOCK_STREAM参数表示基于TCP的流式socket通信,管发管收。SOCK_DGRAM参数表示基于UDP的数据报式传输,只管发,不管收。
1.服务端Socket对象方法
s.bind(address):将套接字绑定到地址,在AF_INET下,以s.bind(host,port)元组的方式传入,如s.bind(host,port)。
s.listen(backlog):开始监听TCP传入连接,backlog指定在拒绝链接前,操作系统可以挂起的最大连接数。
s.accept():接受TCP链接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据,address是链接客户端的地址。
2.服务端Socket对象方法
s.connect(adress):链接到address处的套接字,一般address的格式为tuple(host,port),如果链接出错,则返回socket.error错误。
s.connect_ex(address):功能与s.connect(address)相同,但成功返回0.失败返回errno。
3.公共Socket对象方法
s.recv(bufsize[,flag]):接受套接字数据,数据以字符串的形式返回,bufsize指定要接受的最大数据量。
s.send(string[,flag]):发送TCP数据,将字符串中的数据发送到链接的套接字,返回值是要发送的字节数量,该数量可能小于string的字节大小。
s.sendto(string,address):UDP协议是无连接状态的协议,所以我们在发送数据的过程中没有用connect方法来进行连接。string参数就代表我们要发送的数据,address表示地址(由tuple(host,port)表示)。
s.recvfrom(bufsize[,flag]):接收UDP数据,返回值是tuple(data,address)。其中data是包含接受数据的字符串,address形式为tuple(host,port)的套接字地址。
s.sendall(string[,flag]):完整发送TCP数据,将字符串中的数据发送到链接的套接字,但在返回之前尝试发送所有数据。
s.close():关闭套接字。
s.getpeername():返回套接字的远程地址,返回值通常是一个tuple(ipaddr,port)
s.getsockname():返回套接字自己的地址,返回值通常是一个tuple(ipaddr,port)
s.fileno():返回套接字的文件描述符。
二.简易的服务端和客户端
我们编写一个简易的TCP客户端如下所示:
import socket
target_host="www.baidu.com"
target_port=80
while True:
try:
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect((target_host,target_port))
s=input("Data:")
s=s.encode()
client.send(s)
response=client.recv(4069)print(response)
except Exception as e:
print("Exception:{}".format(e))
client.close()
我们编写一个简易的TCP服务端如下:
import socket
import threading
bind_ip="127.0.0.1"
bind_port=9999
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind((bind_ip,bind_port))
server.listen(5)
print("[*]Listening on %s:%d"%(bind_ip,bind_port))
def handle_client(client_socket):
request=client_socket.recv(1024)
print("[*]Received:%s"%request)
client_socket.send("ACK")
client_socket.close()
while True:
client,addr=server.accept()
print("[*]Accept connection from:%s:%d"%(addr[0],addr[1]))
client_handler=threading.Thread(target=handle_client,args=(client,))
client_handler.start()
我们可以写一个简单的TCP客户端与服务端进行交互:
import socket
target_ip="127.0.0.1"
target_port=9999
while True:
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect((target_ip,target_port))
data=raw_input("[*]Please input your data:")
client.send(data)
response=client.recv(4096)
print("[*]Response data:%s"%response)
client.close()