socket
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket, 又称为“套接字”。
模块
1 import socket
创建套接字
1 socket.socket([family[, type[, proto]]])
family: 套接字家族可以使AF_UNIX或者AF_INET
type: 套接字类型可以根据是面向连接的还是非连接分为
SOCK_STREAM(基于TCP)
或SOCK_DGRAM(基于UDP)
protocol: 一般不填默认为0.
常用函数
sk.bind(address)
s.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。
sk.listen(backlog)
开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。
backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5
这个值不能无限大,因为要在内核中维护连接队列
sk.accept()
接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。
接收TCP 客户的连接(阻塞式)等待连接的到来
sk.connect(address)
连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
sk.close()
关闭套接字
sk.recv(bufsize[,flag])
接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。
sk.send(string[,flag])
将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。
单线程通信
该实例中,只能 client 发一句, server回一句(先启动server,后启动client)
server
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # Author: jyroy 4 5 import socket 6 7 if __name__ == '__main__': 8 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #ipv4, TCP 9 sock.bind(('0.0.0.0',5000)) #元组,相当于一个参数10 sock.listen(10) #同时保持是十个人的连接11 conn, addr = sock.accept()12 while True:13 data = conn.recv(1024) #最多1K的数据14 print(data)15 if data == 'bye':16 break17 else:18 msg = raw_input(">>")19 conn.send(msg)20 sock.close()21 print('Bye!!')
client
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # Author: jyroy 4 5 import socket, time 6 7 if __name__ == '__main__': 8 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 9 sock.connect(('localhost',5000))10 while True:11 msg = raw_input(">>")12 if msg == "bye":13 sock.send(msg)14 sock.close()15 break16 else:17 sock.send(msg)18 data = sock.recv(1024)
多线程通信
在该实例中可以自由发送和接收信息(先启动server,后启动client)
利用threading,多线程进行接受消息和发送消息
callback_recv函数负责接受信息的功能
callback_send函数负责发送信息的功能
server
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # Author: jyroy 4 5 import socket, threading, sys 6 7 8 def callback_send(conn): 9 '''10 11 :param sq:12 :return:13 '''14 while True: #为了维持持续的发送15 msg = raw_input(">>")16 conn.send(msg)17 18 def callback_recv(conn):19 '''20 21 :param sock:22 :return:23 '''24 while True: #为了维持持续的接收25 data = conn.recv(1024)26 print(data)27 28 if __name__ == '__main__':29 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)30 sock.bind(('0.0.0.0',5000)) #元组,相当于一个参数31 sock.listen(10) #同时保持是十个人的连接32 conn, addr = sock.accept()33 34 thread_send = threading.Thread(target=callback_send, args=(conn, ))35 thread_recv = threading.Thread(target=callback_recv, args=(conn, ))36 37 thread_send.start()38 thread_recv.start()39 40 sock.close()
client
#!/usr/bin/env python# -*- coding:utf-8 -*-# Author: jyroyimport socket, time, threading, sysdef callback_send(sock): ''' :param sq: :return: ''' while True: msg = raw_input(">>") sock.send(msg) # if msg in ['bye', 'quit']: # sock.close # breakdef callback_recv(sock): ''' :param sock: :return: ''' while True: data = sock.recv(1024) print(data)if __name__ == '__main__': sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('localhost',5000)) thread_send = threading.Thread(target=callback_send, args=(sock, )) thread_recv = threading.Thread(target=callback_recv, args=(sock, )) thread_send.start() thread_recv.start() while True: pass sock.close()
效果展示
注意
一定要先server程序启动,只有server在等待client之后,client才能找到server进行通信。
我这个只是本机的调试,要和别人通信时,把client程序中,把connect的ip地址,从localhost换成要通信的ip地址