简介
socket编程是一门技术,它主要是在网络通信中经常用到
既然是一门技术,由于现在是面向对象的编程,一些计算机行业的大神通过抽象的理念,在现实中通过反复的理论或者实际的推导,提出了抽象的一些通信协议,基于tcp/ip协议,提出大致的构想,一些泛型的程序大牛在这个协议的基础上,将这些抽象化的理念接口化,针对协议提出的每个理念,专门的编写制定的接口,与其协议一一对应,形成了现在的socket标准规范,然后将其接口封装成可以调用的接口,供开发者使用
目前,开发者开发出了很多封装的类来完善socket编程,都是更加方便的实现刚开始socket通信的各个环节,所以我们首先必须了解socket的通信原理,只有从本质上理解socket的通信,才可能快速方便的理解socket的各个环节,才能从底层上真正的把握
要理解socket必须的得理解tcp/ip,它们之间好比送信的线路和驿站的作用,比如要建议送信驿站,必须得了解送信的各个细节。
TCP/IP协议不同于iso的7个分层,它是根据这7个分层,将其重新划分,好比打扫卫生,本来有扫帚,垃圾斗,抹布,涂料,盆栽等就好比OSI的标准几个分层,tcp/ip根据用途和功能,将扫帚,垃圾斗放到粗略整理层,抹布涂料放到中度整理层,盆栽放到最终效果层。这里TCP/IP也对OSI的网络模型层进行了划分:大致如下:
OSI模型:
TCP/IP协议参考模型把所有的TCP/IP系列协议归类到四个抽象层中
应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等
传输层:TCP,UDP
网络层:IP,ICMP,OSPF,EIGRP,IGMP
数据链路层:SLIP,CSLIP,PPP,MTU
每一抽象层建立在低一层提供的服务上,并且为高一层提供服务,看起来大概是这样子的
通过上面的图形,由于底一层的需要向高一层的提供服务,我们大致的理解应用程序需要传输层的tcp和网络层的ip协议提供服务,但是我们这章要分析的socket它是在tcpip协议的那一部分呢,就好比,我们的通讯线路已经有明确的规定,我们的驿站要设计在哪个地方一样
到目前为止,大致的了解了应用程序和tcpip协议的大致关系,我们只是知道socket编程是在tcp/IP上的网络编程,但是socket在上述的模型的什么位置呢。这个位置被一个天才的理论家或者是抽象的计算机大神提出并且安排出来
我们可以发现socket就在应用程序的传输层和应用层之间,设计了一个socket抽象层,传输层的底一层的服务提供给socket抽象层,socket抽象层再提供给应用层,问题又来了,应用层和socket抽象层之间和传输层,网络层之间如何通讯的呢,了解这个之前,我们还是回到原点
要想理解socket编程怎么通过socket关键词实现服务器和客户端通讯,必须得实现的了解tcp/ip是怎么通讯的,在这个的基础上在去理解socket的握手通讯
在tcp/ip协议中,tcp通过三次握手建立起一个tcp的链接,大致如下
第一次握手:客户端尝试连接服务器,向服务器发送syn包,syn=j,客户端进入SYN_SEND状态等待服务器确认
第二次握手:服务器接收客户端syn包并确认(ack=j+1),同时向客户端发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态
服务端code
import socket
BUF_SIZE = 1024
#设置缓冲区大小
server_addr = ('127.0.0.1',8888)
# ip 和端口号构成,表示地址
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 生成一个新的socket对象
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 设置地址复用
server.bind(server_addr)
# 绑定地址
server.listen(5)
# 监听,最大监听数5
while True:
client,client_addr = server.accept()
# 接受TCP连接,并返回新的套接字和地址
print('Connected by ',client_addr)
while True:
data = client.recv(BUF_SIZE)
# 从客户端接受数据
print(data)
send='You are Dog!'
client.sendall(send.encode())
# 发送数据到客户端
server.close()
客户端code
import socket
BUF_SIZE = 1024
#设置缓冲区大小
server_addr = ('127.0.0.1',8888)
# ip 和端口号构成,表示地址
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 返回新的socket对象
client.connect(server_addr)
# 要连接的服务器地址
while True:
data = input("Please input some string >")
client.sendall(data.encode())
# Python3需要用encode函数将object对象转换为字符串,等价于 str(data,'UTF-8')
data = client.recv(BUF_SIZE)
# 从服务器端接收数据
print(data)
client.close()
pycharm setting
目的,运行一个程序就打开一个输出console。默认是只打开一个console的
1-
2-
服务端
客户端
---------
使用错误捕获的socket通信
服务器端
import sys
import socket
BUF_SIZE = 1024
# 设置缓冲区大小
server_addr = ('127.0.0.1', 8888)
# IP和端口构成表示地址
try:
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 生成一个新的socket对象
except socket.error as msg:
print("Creating Socket Failure,Error Code :" + str(msg[0]) + " Message : " + msg[1])
sys.exit()
print("Socket Created !")
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 设置地址复用
try:
server.bind(server_addr)
# 绑定地址
except socket.error as msg:
print("Binding Failure .Error Code :" + str(msg[0]) + " Message: " + str(msg[1]))
sys.exit()
print("Socket Bind !")
server.listen(5)
# 最大监听数5
print("Socket Listening !")
while True:
client, client_addr = server.accept()
# 接收TCP连接,并返回新的套接字和地址,阻塞函数
print("Connected by ", client_addr)
while True:
data = client.recv(BUF_SIZE)
# 从客户端接收数据
print(data)
client.sendall(data)
# 发送数据到客户端
server.close()
客户端
import sys
import socket
BUF_SIZE = 1024
server_addr = ('127.0.0.1',8888)
try:
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
except socket.error as msg:
print("Creating Socket Failure .Error Code : "+str(msg[0])+" Message: "+str(msg[1]))
sys.exit()
client.connect(server_addr)
while True:
data = input("Please input some string ->:")
if not data:
print("input can`t empty,Please input again...")
continue
client.sendall(data.encode())
# 发送数据到服务器
data =client.recv(BUF_SIZE)
# 从服务器端接收数据
print(data)
client.close()
连接的端口是8888,监听5个端口,客户端连接服务器时,会被随机分配端口。