socket:是在应用层和传输层之间的一个抽象层,它把TCP/IP层的复杂的操作封装抽象,并提供一些接口供应用层调用

套接字:被设计用于同一台主机上多个应用程序之间的通信,被称为进程之间通信或IPC
  基于文件类型的套接字:AF_UNIX
    UNIX一切皆文件,基于文件的套接字调用的就是底层文件系统来抓取数据,两个套接字进程运行在同一机器
    可以访问同一文件系统间接完成通信
  基于网络类型的套接字:AF_INET

套接字工作流程

套接字工作流程:服务端先初始化socket(),然后与端口进行绑定bind(),对端口监听listen(),调用accept()阻塞,
  直到等到客户端连接,这时如果客户端初始化一个socket(),然后连接服务器connect(),如果连接成功,则客户端和服务端建立连接。
  客户端发送请求,服务端接收请求并处理请求,然后把处理的数据回复给客户端,客户读取数据,最后关闭连接,交互结束

基于tcp协议的套接字:tcp是基于链接的,必须先启动服务端,再启动客户端

#服务端
import socket ip_port = ("127.0.0.1", 8000)
back_log = 5
buffer_size = 1024 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 参数分别为(基于网络通讯,TCP协议),表示基于TCP协议的网络通讯
phone.bind(ip_port) # 参数为IP地址和端口号,以元组的形式放进参数里,且IP地址是字符串
phone.listen(back_log) # 表示当前可以有几个链接
print("--->")
while True: #设定循环,可以接收多个链接
conn, addr = phone.accept( ) # 等待客户端信息,得到两个数据,一个是(对方的链接,一个是对方的通讯地址),元组形式 while True: #循环,服务端和客户端能循环多次的传输数据
try: #客户端断开链接时,服务端也会断开链接,这时循环时就会出现异常,需要处理异常
data = conn.recv(buffer_size) # 接收客户端信息,参数代表可以接收多少字节,得到的是二进制形式的数据
print("接到客户端信息:", data.decode("utf-8"))
conn.send(data.upper( )) # 向客户端回传信息
except Exception:
break
conn.close() phone.close()
#客户端
import socket
ip_port = ("127.0.0.1",8000)
back_log = 5
buffer_size = 1024 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(ip_port) #链接服务端 while True:
msg = input(">>>")
if not msg:continue #输入为空时,可以send到自己的缓存中,但os不会将空发给硬件,对方便recv不到数据
phone.send(msg.encode("utf-8")) #向服务端传内容,传输的是二进制格式
data = phone.recv(buffer_size) #获取服务端传回的内容
print("收到服务端发来的消息:",data) phone.close()

补充1:

应用程序和os都是先加载到缓存再使用,所有操作都是对缓存读取和传输数据,只有os才可以操作硬件

应用程序将数据send到缓存中,然后由os操作传给硬件,再进行网络传输,对方在recv到(recv也是从缓存中recv数据)

如果send的数据为空,可以send到自己的缓存中,但recv不到空

补充2:

对于服务端来说,客户端断开链接,服务端accept不到链接,就会出现异常,程序就会停止,可以加个异常处理

补充3:

有时重启服务端时会出现异常:address already in use,这是断开链接时进入四次挥手,但time_wait状态在占用地址

可以加一个socket配置,重用IP和端口

在phone.bind()前加一个phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)

基于udp协议的套接字:udp是无链接传输,先启动哪边都不会报错,可以实现并发,同时与多个客户端通讯

from socket import *         #将socket下的所有属性都导入过来,这样可以直接使用属性

ip_port = ("127.0.0.1",8080)
buffer_size = 1024 udp_server = socket(AF_INET,SOCK_DGRAM) #DGRAM表示数据报式套接字
udp_server.bind(ip_port) while True:
data,addr = udp_server.recvfrom(buffer_size) #接收到客户端发过来是数据加客户端的IP和端口
print(data,addr)
udp_server.sendto(data.upper(),addr) #无链接需要指定客户端的IP和端口
from socket import *

ip_port = ("127.0.0.1",8080)
buffer_size = 1024 udp_client = socket(AF_INET,SOCK_DGRAM) while True:
msg = input(">>")
udp_client.sendto(msg.encode("utf-8"),ip_port) #sendto需要指定发送到哪个IP和端口
data,addr = udp_client.recvfrom(buffer_size)
print(data.decode("utf-8")) udp_client.close()

补充1:

udp协议send一个空,依然可以fevcfrom到一个空

最新文章

  1. 【代码笔记】iOS-获得现在的周的日期
  2. C# 访问数据库
  3. Android Listview
  4. MFC之鼠标消息处理
  5. java面向对象基础
  6. 烂泥:ubuntu下配置msmtp+mutt发送邮件
  7. 【转】css学习专题-BFC
  8. [ActionScript 3.0] AS3.0 将图像的Alpha通道转换为黑白图像(分离ARGB方式)
  9. Aptana Studio3开发Python和Ruby(最佳工具)
  10. 360兼容模式==ie8 兼容模式下 span标签占位问题
  11. 改进duilib的richedit控件的部分功能
  12. Android TextView自动实现省略号
  13. (转)ThinkPHP使用心得分享-分页类Page的用法
  14. 线程、线程句柄、线程ID
  15. [转载] 基于Dubbo框架构建分布式服务
  16. Win10构建Python全栈开发环境With WSL
  17. eclipse与visualVM与mat
  18. JAVA微信公众号通过openid发送模板消息~
  19. vue图表
  20. jQuery左侧图片右侧文字滑动切换代码

热门文章

  1. Oracle数据库用户的密码过期问题处理
  2. TiDB单机安装测试
  3. Windows程序调用dll
  4. 学习Linux的基础网站
  5. Jackson常用注解及用法
  6. element_to_be_clickable(locator)
  7. 【Appium遇到的坑】环境配置无误,路径无中文,无空格,提示error: Logcat capture failed: spawn ENOENT
  8. sentos7网卡改名
  9. oracle数据库表空间创建&导入&导出
  10. spring -boot定时任务 quartz 基于 MethodInvokingJobDetailFactoryBean 实现