1. 套接字
套接字是计算机网络数据结构,它体现了上节中所描述的“通信端点”的概念。在任何
类型的通信开始之前,网络应用程序必须创建套接字。可以将它们比作电话插孔,没有它将
无法进行通信。
有两种类型的套接字:基于文件的和面向网络的。
UNIX 套接字是我们所讲的套接字的第一个家族,并且拥有一个“家族名字”。(这块不是本文重点,不细说)
而基于网络的套接字,有自己的家族名字 AF_INET。
Python 只支持 AF_UNIX、 AF_NETLINK、 AF_TIPC 和 AF_INET 家族。在网络编程中,将会用到 AF_INET。
-
面向连接
实现这种连接类型的主要协议是传输控制协议(更为人熟知的是它的缩写 TCP)。为 了
创建 TCP 套接字,必须使用 SOCK_STREAM 作为套接字类型。 -
面向无连接
实现这种连接类型的主要协议是用户数据报协议(更为人熟知的是其缩写 UDP)。为 了
创建 UDP 套接字,必须使用 SOCK_DGRAM 作为套接字类型。
2. socket()模块函数
要创建套接字,必须使用 socket.socket()函数,它一般的语法如下。
socket(socket_family, socket_type, protocol=0)
为了创建 TCP/IP 套接字,可以用下面的方式调用 socket.socket()。
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
同样,为了创建 UDP/IP 套接字,需要执行以下语句。
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
3. 创建TCP服务器
伪代码如下:
# -*- coding: utf-8 -*
from socket import *
ss = socket() # 创建服务器套接字
ss.bind() # 套接字与地址绑定
ss.listen() # 监听连接
inf_loop: # 服务器无限循环
cs = ss.accept() # 接受客户端连接
comm_loop: # 通信循环
cs.recv()/cs.send() # 对话(接收/发送)
cs.close() # 关闭客户端套接字
ss.close() # 关闭服务器套接字#(可选)
在程序中,如果想要完成一个tcp服务器的功能,需要的流程如下:
- socket创建一个套接字
- bind绑定ip和port
- listen使套接字变为可以被动链接
- accept等待客户端的链接
- recv/send接收发送数据
3.1 一个很简单的tcp服务器如下:
#coding=utf-8
from socket import *
# 创建socket
tcpSerSocket = socket(AF_INET, SOCK_STREAM)
# 绑定本地信息
address = ('', 7787)
tcpSerSocket.bind(address)
# 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了
tcpSerSocket.listen(5)
# 如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务器
# newSocket用来为这个客户端服务
# tcpSerSocket就可以省下来专门等待其他新客户端的链接
newSocket, clientAddr = tcpSerSocket.accept()
# 接收对方发送过来的数据,最大接收1024个字节
recvData = newSocket.recv(1024)
print('接收到的数据为:',recvData)
# 发送一些数据到客户端
newSocket.send("thank you !".encode())
# 关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接
newSocket.close()
# 关闭监听套接字,只要这个套接字关闭了,就意味着整个程序不能再接收任何新的客户端的连接
tcpSerSocket.close()
tcp的客户端要比服务器端简单很多,如果说服务器端是需要自己买手机、查手机卡、设置铃声、等待别人打电话流程的话,那么客户端就只需要找一个电话亭,拿起电话拨打即可,流程要少很多。
3.2 一个很简单的客户端如下:
#coding=utf-8
from socket import *
# 创建socket
tcpClientSocket = socket(AF_INET, SOCK_STREAM)
# 链接服务器
serAddr = ('10.88.2.192', 7787)
tcpClientSocket.connect(serAddr)
# 提示用户输入数据
sendData = input("请输入要发送的数据:")
tcpClientSocket.send(sendData.encode())
# 接收对方发送过来的数据,最大接收1024个字节
recvData = tcpClientSocket.recv(1024)
print('接收到的数据为:',recvData)
# 关闭套接字
tcpClientSocket.close()
注:以上服务端、客户端的代码已经在python3下调试通过,调试的过程中,也碰到了一些问题,记录如下:
- 出错NameError: name 'raw_input' is not defined
原因出在raw_input ,python3.0版本后用input替换了raw_input 。所以是自己看的教程太老,基于python2.x,而自己用的是3.x,所以使用input就好了。 - 调试时出错TypeError: a bytes-like object is required, not 'str'
这个也是版本的问题,python3.5和Python2.7在套接字返回值解码上有区别。
参考文章:https://blog.csdn.net/yexiaohhjk/article/details/68066843
(未完待续,待整理)
网友评论