套接字
套接字是一种具有之前所说的“通讯端点”概念的计算机网络数据结构。网络化的应用程序在开始任何通讯之前都必需要创建套接字。就像电话的插口一样,没有它就完全没办法通讯。
套接字分为两种,分别是基于文件型和基于网络型,这里主要介绍基于网络型的AF_INET。
TCP连接
TCP
连接是基于字节流,面向连接的,顺序的,可靠的,不会重复传输数据;每一个数据会被拆分成多份,每一份都会不多不少地正确到达目的地。然后被重新按顺序拼装起来,传给正在等待的应用程序。
TCP
连接必须建立连接才能通讯,导致对系统资源的消耗较大,并且因为有确认机制、三次握手机制,这些也导致TCP容易被人利用,实现DOS
、DDOS
、CC
等攻击。适用于对数据完整性,准确性较高的场景,例如HTTP
,FTP
,SMTP
等等。
UDP连接
UDP
连接为数据报型的无连接套接字,无需建立连接便可进行通讯,但是数据到达的顺序,可靠性和不重复性很难保证,数据报的数据边界会保留,不会像 TCP
那样会被拆分成很多份。
但是因为UDP无需像TCP
那样保持连接,占用的系统资源也相对较少,适用于即时通讯,在线语音等等。
socket模块
Python
当中使用socket
模块提供基本基于套接字的网络通讯。模块中socket()
用来创建套接字,使用格式如下:
# socket_family指AF_INET或AF_UNIX
# socket_type指SOCK_STREAM或SOCK_DGRAM
# protocol 一般不填写,默认为0
socket(socket_family, socket_type, protocol=0)
例如创建TCP
套接字如下:
tcpSock = socket.socket(sock.AF_INET, socket.SOCK_STREAM)
创建UDP
套接字:
tcpSock = socket.socket(sock.AF_INET, socket.SOCK_DGRAM)
创建套接字后需要了解其他常用函数:
函数 | 使用 | TCP/UDP |
---|---|---|
sock.bind() | 绑定主机地址和端口 | TCP/UDP |
sock.listen() | 开始TCP监听 | TCP |
sock.accept | 接受TCP连接 | TCP |
sock.connect() | 主动初始化TCP连接 | TCP |
sock.connect_ex() | 主动初始化TCP连接,出错返回出错码 | TCP |
sock.recv() | 接收TCP数据 | TCP |
sock.send() | 发送TCP数据 | TCP |
sock.sendall() | 发送完整TCP数据 | TCP |
sock.recvfrom() | 接收UDP数据 | UDP |
sock.sendto() | 发送UDP数据 | UDP |
sock.getpeername() | 连接到当前套接字的远程地址 | TCP/UDP |
sock.getsockname() | 当前套接字地址 | TCP/UDP |
sock.close() | 关闭套接字 | TCP/UDP |
接下来演示时间服务器的TCP
和UDP
程序, 服务端接收到客户端的数据后,加上时间后返回为客户端:
TCP 服务端:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from socket import *
from time import ctime
host = "127.0.0.1"
port = 21567
BUFSIZE=1024
addr = (host, port)
tcpServerSocket = socket(AF_INET, SOCK_STREAM)
tcpServerSocket.bind(addr)
tcpServerSocket.listen(5)
while True:
print "Waiting for Connections..."
tcpClientSocket, inaddr = tcpServerSocket.accept()
print "connected from:", inaddr
while True:
data = tcpClientSocket.recv(BUFSIZE)
if not data:
break
tcpClientSocket.send('[%s] %s' %(ctime(), data))
tcpClientSocket.close()
tcpServerSocket.close()
TCP 客户端:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from socket import *
from time import ctime
ServerHost = "127.0.0.1"
ServerPort = 21567
BUFSIZE=1024
addr = (ServerHost, ServerPort)
tcpClientSocket = socket(AF_INET, SOCK_STREAM)
tcpClientSocket.connect(addr)
while True:
data = raw_input('> ')
if not data:
break
tcpClientSocket.send(data)
data = tcpClientSocket.recv(BUFSIZE)
if not data:
break
print data
tcpClientSocket.close()
UDP 服务端:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from socket import *
from time import ctime
host = "127.0.0.1"
port = 21567
BUFSIZE=1024
addr = (host, port)
udpServerSocket = socket(AF_INET, SOCK_DGRAM)
udpServerSocket.bind(addr)
while True:
print "Waiting for Connections..."
data, inaddr = udpServerSocket.recvfrom(BUFSIZE)
print "connected from:", inaddr
udpServerSocket.sendto('[%s] %s' %(ctime(), data), inaddr)
udpServerSocket.close()
UDP 客户端:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from socket import *
from time import ctime
host = "127.0.0.1"
port = 21567
BUFSIZE=1024
addr = (host, port)
udpClientSocket = socket(AF_INET, SOCK_DGRAM)
while True:
data = raw_input("> ")
if not data:
break
udpClientSocket.sendto(data, addr)
data, addr= udpClientSocket.recvfrom(BUFSIZE)
if not data:
break
print data
udpClientSocket.close()
时间戳服务器程序参考《Python核心教程》