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
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- # Author: jyroy
- import socket
- if __name__ == '__main__':
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #ipv4, TCP
- sock.bind(('0.0.0.0',5000)) #元组, 相当于一个参数
- sock.listen(10) #同时保持是十个人的连接
- conn, addr = sock.accept()
- while True:
- data = conn.recv(1024) #最多 1K 的数据
- print(data)
- if data == 'bye':
- break
- else:
- msg = raw_input(">>")
- conn.send(msg)
- sock.close()
- print('Bye!!')
- client
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- # Author: jyroy
- import socket, time
- if __name__ == '__main__':
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.connect(('localhost',5000))
- while True:
- msg = raw_input(">>")
- if msg == "bye":
- sock.send(msg)
- sock.close()
- break
- else:
- sock.send(msg)
- data = sock.recv(1024)
多线程通信
在该实例中可以自由发送和接收信息(先启动 server, 后启动 client)
利用 threading, 多线程进行接受消息和发送消息
callback_recv 函数负责接受信息的功能
callback_send 函数负责发送信息的功能
- server
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- # Author: jyroy
- import socket, threading, sys
- def callback_send(conn):
- '''
- :param sq:
- :return:
- '''
- while True: #为了维持持续的发送
- msg = raw_input(">>")
- conn.send(msg)
- def callback_recv(conn):
- '''
- :param sock:
- :return:
- '''
- while True: #为了维持持续的接收
- data = conn.recv(1024)
- print(data)
- if __name__ == '__main__':
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.bind(('0.0.0.0',5000)) #元组, 相当于一个参数
- sock.listen(10) #同时保持是十个人的连接
- conn, addr = sock.accept()
- thread_send = threading.Thread(target=callback_send, args=(conn, ))
- thread_recv = threading.Thread(target=callback_recv, args=(conn, ))
- thread_send.start()
- thread_recv.start()
- sock.close()
- client
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- # Author: jyroy
- import socket, time, threading, sys
- def callback_send(sock):
- '''
- :param sq:
- :return:
- '''
- while True:
- msg = raw_input(">>")
- sock.send(msg)
- # if msg in ['bye', 'quit']:
- # sock.close
- # break
- def 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 地址
关于 python 网络编程的其他资料:
菜鸟教程 --http://www.runoob.com/python/python-socket.html
python 官方 --https://docs.python.org/3/library/socket.html
来源: https://www.cnblogs.com/jyroy/p/9785665.html