1.socket编程的概念
-
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求;
-
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作;
-
线程之间的通信形式有:event时间,lock锁,信号量,queue队列等;
-
进程之间的通信,一般使用套接字,套接字的IPC方式使得跨平台之间的进程通信成为可能,最早的socket是在BSD-Unix平台上发布,最终成为了行业标准,使得计算机之间的通信变得非常简单;
2.socket( )类详解
-
套接字格式:
socket(family, type[,protocal])
使用给定的套接族,套接字类型,协议编号(默认为0)来创建套接字 ; -
socket.AF_UNIX
:用于同一台机器上的进程通信(既本机通信); -
socket.AF_INET
:用于服务器与服务器之间的网络通信; -
socket.AF_INET6
:基于IPV6方式的服务器与服务器之间的网络通信; -
socket.SOCK_STREAM
:基于TCP的流式socket通信; -
socket.SOCK_DGRAM
:基于UDP的数据报式socket通信; -
socket.SOCK_RAW
:原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以,其次SOCK_RAW也可以处理特殊的IPV4报文,此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头; -
socket.SOCK_SEQPACKET
:可靠的连续数据包服务;
3.TCP服务器端代码实现
import socket
from pprint import pprint
# 创建TCP连接
socket_instance = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_instance.bind(('127.0.0.1', 9000))
# 操作系统可以挂起的最大连接数,如果同一时间的连接数超过5,拒绝其他的连接
socket_instance.listen(5)
# 循环接收新的客户端连接
while True:
# 接收客户端的请求,且获取新socket对象和客户端信息
new_socket, client_addr = socket_instance.accept()
# 循环接收已连接的客户端发送的数据
while True:
# 从缓存区中读取1024字节信息
data = new_socket.recv(1024).decode()
# 返回客户端的一下信息
pprint(data)
# 返回客户端地址 ('127.0.0.1', 51978)
pprint(client_addr)
# 发送数据
new_socket.sendall('Server has received your msg'.encode())
4.TCP客户端代码实现
import socket
# 创建TCP连接
socket_instance = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_instance.connect(('127.0.0.1', 9000))
while True:
cmd = input("请输入您想说的话:")
socket_instance.send(cmd.encode())
data = socket_instance.recv(1024)
print(data)
5.UDP服务器端代码实现
import socket
# 创建UDP连接
socket_instance = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socket_instance.bind(('127.0.0.1', 9000))
# 循环接收新的客户端连接
while True:
# 接收客户端的请求,且获取新socket对象和客户端信息
data, client_addr = socket_instance.recvfrom(1024)
print(data.decode())
socket_instance.sendto('Server has receive your data'.encode(), client_addr)
6.UDP客户端代码实现
import socket
# 创建socket实例
socket_instance = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
data = input("请输入您想说的话:")
socket_instance.sendto(data.encode(), ('127.0.0.1', 9000))
data, server_addr = socket_instance.recvfrom(1024)
print(data.decode())
7.服务器端socket实例对象创建连接的方法有:
-
bind()
:将套接字绑定到地址,在AF_INET下,以tuple(host, port)的方式传入; -
listen()
:开始监听TCP传入连接; -
accept()
:接受TCP链接并返回(new_socket, address),其中new_socket是新的套接字对象,可以用来接收和发送数据,address是链接客户端的地址;
8.客户端socket实例对象创建连接的方法有:
-
connect()
:连接到address处的套接字,一般address的格式为tuple(host, port),如果链接出错,则返回socket.error错误; -
connect_ex()
:功能与s.connect(address)相同,但成功返回0,失败返回errno的值;
9.客户端和服务器端socket实例对象都有的方法:
-
recv()
:接受TCP套接字的数据,数据以字符串形式返回; -
send()
:发送TCP数据,将字符串中的数据发送到链接的套接字,返回值是要发送的字节数量,该数量可能小于string的字节大小; -
sendall()
:完整发送TCP数据,将字符串中的数据发送到链接的套接字,但在返回之前尝试发送所有数据,成功返回None,失败则抛出异常; -
recvfrom()
:接受UDP套接字的数据; -
sendto()
:发送UDP数据,将数据发送到套接字; -
close()
:关闭套接字; -
getpeername()
:返回套接字的远程地址; -
getsockname()
:返回套接字自己的地址; -
settimeout()
:设置套接字操作的超时时间; -
gettimeout()
:返回当前超时值,单位是秒,如果没有设置超时则返回None; -
fileno()
:返回套接字的文件描述; -
setblocking()
:如果flag为0,则将套接字设置为非阻塞模式,否则将套接字设置为阻塞模式(默认值); -
makefile()
:创建一个与该套接字相关的文件; -
setsockopt()
:设置给定套接字选项的值; -
getsockopt()
:返回套接字选项的值;
10.TCP 和UDP的区别有哪些
-
TCP传输数据使用字节流的方式传输,而UDP是数据报传输;
-
TCP对网络条件要求高,而UDP更适合实时传输;
-
TCP编程可以保证传输的可靠性,UDP则不保证;
-
TCP会产生粘包现象,而UDP则容易丢包;
-
TCP使用listen方法和accpet方法,而UDP不需要;
-
TCP使用recv方法和send方法,而UDP使用recvfrom方法和sendto方法;
11.UDP 服务器端的实现步骤
-
创建 socket 对象;
-
向socket 对象绑定服务器地址;
-
进入与客户端交互数据的循环阶段;
-
接收客户端发来的数据(包括 bytes 对象 data,以及客户端的 IP 地址和端口号 addr,其中 addr 为二元组 (host, port);
-
打印接收信息,表示从地址为 addr 的客户端接收到数据);
-
关闭;
12.UDP客户端的实现步骤
-
创建 socket 对象;
-
初始化 UDP 服务器的地址;
-
进入与服务器交互数据的循环阶段;
-
等待用户输入数据;
-
向服务器端发送接收数据;
-
关闭套接字,不再向服务器发送数据;
网友评论