套接字:进行网络通信的一种手段socket
1.流式套接字(SOCK_STREAM):传输层基于tcp协议进行通信
2.数据报套接字(SOCK_DGRAM):传输层基于udp协议进行通信
3.原始套接字(SOCK_RAW):访问底层协议的套接字
套接字编程:
1.TCP服务端()
0.导入socket模块
from socket import *
1.创建套接字
socket(socket_family=AF_INET,socket_type=SOCK_STREAM,proto=0)
功能:创建套接字
参数:socket_family:选择地址族种类 AF_INET(UNIX)
socket_type:套接字类型 SOCK_STREAM(流式套接字)
SOCK_DGRAM(数据报套接字)
proto:子协议类型默认为0
返回值:返回创建的套接字
2.绑定IP和端口号(上一步返回套接字对象名为sockfd)
sockfd.bind()
功能:绑定IP和端口
参数:是一个元组,第一项是字符串形式的IP,第二项是端口号,示例("192.168.1.2",8888)
返回值:无
3.让套接字具有监听功能
sockfd.listen(n)
功能:是套接字变为监听套接字,同时创建监听队列
参数:n 监听队列大小(n在linux下不起作用)
返回值:无
4.等待客户端连接
sockfd.accept()
功能:阻塞等待客户端连接
参数:无
返回值:1.返回一个客户端专属的新套接字用来和客户端通信
2.返回连接的客户端地址
示例:connfd,addr = sockfd.accept()
5.消息的收发(用上一步返回的新套接字connfd)
1.recv(buffer)
功能:接收消息
参数:一次接收消息的大小,单位:字节
返回值:返回接收到的内容
示例:connfd.recv(1024)
2.send(data)
功能:发送消息
参数:发送的内容(发送byte格式的)
返回值:发送了多少字节(整数)
示例:connfd.send(b"你好,客户端--服务端发送");
3.sendall()
功能:同send
返回值:发送成功返回none,失败产生异常

注意:当没有接收端的时候,send操作会导致broken pipe

6.关闭套接字
close()
功能:关闭套接字(所有套接字都要关闭)
示例:sockfd.close()
connfd.close()

2.TCP客户端流程
1.创建流式套接字
2.发起连接请求
connect()
功能:发起连接
参数:元组 (1.服务器ip,2.port)
返回值:无
3.收发消息
4.关闭套接字

3.示例
#tcp测试服务端 my_tcp_server.py
from socket import *
# 创建连接
sockfd = socket(AF_INET,SOCK_STREAM)
#绑定ip和端口号
sockfd.bind(("0.0.0.0",18888))
#设置监听套接字
sockfd.listen(10)
while True:
#等待连接
print("waiting for connect...")
connfd,addr = sockfd.accept()
print("connect from",addr)
#收发消息
while True:
cli_msg = connfd.recv(5)
if not cli_msg:
break
print(cli_msg.decode())
serv_msg = input("服务端消息>")
connfd.send(serv_msg.encode())
connfd.close()

sockfd.close()
=========================================
#TCP测试客户端 my_tcp_clinet.py
from socket import *

sockfd = socket(AF_INET,SOCK_STREAM)
sockfd.connect(("192.168.1.4",18888))
while True:
cli_msg = input("客户端消息>")
if not cli_msg:
break
sockfd.send(cli_msg.encode())
serv_msg = sockfd.recv(1024)
print(serv_msg.decode())

sockfd.close()

4.UDP通信
1.创建数据报套接字
sockfd = socket(AF_INET,SOCK_DGRAM)
2.绑定服务端地址
ipaddr = ("192.168.1.4",18888)
sockfd.bind(addr)
3.收发消息
1. data,addr = sockfd.recvfrom(buffersize)
功能:接收数据报套接字消息
参数:每次最多接收消息的大小 字节
返回值:data: 接收到的消息
addr:消息发送者的地址
注意:一次接收一个数据包,如果数据包一次没有接收完则会丢失没接收的内容
2. sockfd.sendto(data,addr)
功能:发送消息
参数: data 要发送的消息
addr 发送给某个主机的地址
返回值:发送消息的字节数
4.关闭套接字
sockfd.close()
5.示例:
#UDP测试服务端 udp_server.py
from socket import *
import sys
from time import ctime
#从命令行传入参数
#python3 udp_server.py 192.168.1.4 18888
HOST = sys.argv[1]
PORT = int(sys.argv[2])
ADDR = (HOST,PORT)
BUFFERSIZE = 1024

#创建数据报套接字
sockfd = socket(AF_INET,SOCK_DGRAM)
#绑定地址
sockfd.bind(ADDR)
print("udp已启动...")
#收发消息
while True:
data,addr = sockfd.recvfrom(BUFFERSIZE)
print("recv from %s : %s" % (addr,data.decode()))
sockfd.sendto(f"{ctime()} 接收到 {addr} 的消息".encode(),addr )

sockfd.close()
=============================================
#udp测试客户端 udp_client.py
from socket import *
import sys
from time import ctime
#从命令行传入参数
#python3 udp_client.py 192.168.1.4 18888
HOST = sys.argv[1]
PORT = int(sys.argv[2])
ADDR = (HOST,PORT)
BUFFERSIZE = 1024
sockfd = socket(AF_INET,SOCK_DGRAM)

while True:
msg = input("发往服务端数据>>")
if not msg:
break
sockfd.sendto(msg.encode(),ADDR)
data,addr = sockfd.recvfrom(BUFFERSIZE)
print("从服务端收到:",data.decode())

sockfd.close()

套接字属性:
1.创建套接字
s = socket.socket() #示例创建流式套接字,使用默认参数
2.属性:
1. s.fileno()
功能:获取套接字的描述符
*描述符:每一个IO操作系统都会分配一个不同的整数与之对应,该整数即为此IO操作的描述符
返回值:整数
2. s.type (属性):套接字的类型
3. s.getsockname()
功能:获取套接字bind以后绑定的地址
返回值:元组,("ip",port)
4. conn.getpeername()
功能:使用s.accept生成的conn套接字调用,获取该套接字对应客户端的地址
返回值:元组,("ip",port)
5. s.setsockopt(level,optname,value)
功能:设置套接字选项
参数: level: 要定义的选项类型
常用的可选值: IPPROTO_TCP IPPROTP_IP SOL_SOCKET(这个最常用)
optname:根据level确定的子选项
value: 根据选项设置的值
* 选项太多,应用时需要参考手册
示例: s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
设置服务器程序结束之后,端口号可以立马被重用
s.getsockopt(level,optname)
功能:获取套接字选项
参数:同setsockopt
返回值:返回相应选项的值

应用:
1.udp应用之广播(要将套接字设置为允许接收广播)
功能:将消息发送给局域网内所有终端,所以需要发送到.255地址来广播
示例:
#广播测试发送端 broadcast_send.py
from socket import *
from time import sleep
# "192.168.1.255" 可以用 <broadcast> 代替
dest = ("192.168.1.255",19999)
s= socket(AF_INET,SOCK_DGRAM)
s.setsockopt(SOL_SOCKET,SO_BROADCAST,1)
print("发送端已运行...")
while True:
sleep(1)
s.sendto("坚决拥护张大大".encode(),dest)
data,addr = s.recvfrom(1024)
print(f"从{addr}接收到:{data.decode()}")
s.close()
===================================
#广播测试接收端 broadcast_recv.py
from socket import *
HOST = ""
PORT = 19999
#create socket
s = socket(AF_INET,SOCK_DGRAM)
# set socket can receive broadcast
s.setsockopt(SOL_SOCKET,SO_BROADCAST,1)
#绑定接收端的端口号
s.bind((HOST,PORT))
print("接收端已运行.....")
while True:
try:
message,addr = s.recvfrom(4096)
print(f"从{addr}获取信息:{message.decode()}")
s.sendto(b"I am here",addr)
except Exception as e:
print(e)
s.close()
注意:
广播风暴:在一个网络中大量发送广播会占用大量带宽

2.TCP应用之 http传输
1.http协议(超文本传输协议)
1.客户端(浏览器)发起http请求
2.传输层使用TCP协议建立连接,层层打包将请求内容发送给服务器
3.web服务器解包后解析http请求,交给后端应用程序处理
4.后端应用得到结果,通过web服务器回发给前端
2.用途:网站中网页的传输和数据传输,也可用作基于http协议的编程传输数据
3.特点:
1.应用层协议,传输层用tcp连接,简单,灵活,连接使用方便
2.几乎支持所有的数据类型
3.是无状态的
4.持续连接

4.步骤
请求(request)
格式:
请求行:确定具体的请求类型
请求头:对请求内容的信息描述
空行
请求体:具体的请求参数
详细:
请求行:GET /index.html HTTP/1.1
请求方法 请求资源 协议版本
请求方法:
GET 获取网络资源
POST 提交一定的附加数据,得到返回结果
HEAD 获取响应的头信息
PUT 更新服务器资源
DELETE 删除服务器资源
TRACE 用于测试
CONNECT 保留方法
OPTIONS 请求获取服务器性能和信息
*一般只用GET和POST
请求头:很多内容
请求体:
get请求:get参数 示例:&a=1&b=2
post请求:post内容
响应(response)
格式:
响应行:反馈响应的情况
响应头:对响应的具体描述
空行
响应体:具体返回给用户的内容
详细:
响应行:HTTP/1.1 200 OK
协议版本 响应码 信息
响应码:
1xx:提示信息,表示请求已经接收,正在处理
2xx:请求响应成功
3xx:重定向,完成任务需要的其他操作
4xx:客户端错误
5xx:服务端错误
示例:
200 成功
401 没有访问权限
404 资源不存在
500 服务器发生未知错误
503 服务器暂时无法执行
响应头:同请求头
响应体:文件,图片....

TCP应用
1.http服务器
1.接收http请求
2.给出一定的响应
2.示例
#简单的http服务器示例 HttpServer.py
#静态网页处理
#采用循环模式,无法满足客户端长连接

from socket import *
HOST = "0.0.0.0"
PORT = 15555

#处理客户端请求
def handleClient(conn):
request = conn.recv(4096)
requestHeadlers = request.splitlines()
for line in requestHeadlers:
print(line)
try:
f = open("django.html","r",encoding="utf8")
except IOError:
response = "HTTP/1.1 404 not found\r\n"
response += "\r\n"
response += "=====sorry,file not find"
else:
response = "HTTP/1.1 200 ok\r\n"
response += "\r\n"
print(response)
for i in f:
response += i
finally:
conn.send(response.encode())
f.close()
print("任务完成")
#流程控制
def main():
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind((HOST,PORT))
s.listen(10)
while True:
conn,addr = s.accept()
handleClient(conn)
if __name__ == "__main__":
main()

IO操作:在内存中存在数据交换的操作
1.定义
1.内存和磁盘交换: 文件读写 打印
2.内存和网络交换: 上传,下载等
2.程序分类
1.IO密集型
程序中执行大量的IO操作,而较少需要cpu运算:消耗cpu资源少,运行周期往往较长
2.CPU密集型程序
程序执行中需要大量的cpu运算,IO操作比较少:占用cpu多
3.IO分类(阻塞:1.等待某种条件达成再继续运行 2.处理IO事件的耗时较长也会产生阻塞)
1.阻塞IO:默认就是阻塞IO,效率最低的一种IO
2.非阻塞IO:通过修改IO对象使其变为非阻塞状态(改变第一种阻塞形态)
特点:通常用循环不断判断阻塞条件,需要消耗更多cpu,但是一定程度上提高了IO效率
s.setblocking()
功能:将套接字设置为非阻塞状态
参数:bool 默认为True,设置为False则为非阻塞
用法:用循环配合判断阻塞状态

超时等待(检测):对原本阻塞的函数进行设置,使其不再始终阻塞,而是阻塞等待一定
时间后自动返回,在规定时间中如果正常结束阻塞则继续执行,负责将产生timeout异常
s.settimeout(sec)
功能:设置套接字的超时检测
参数:超时时间(秒)
注意:套接字超时检测是用settimeout,还有其他的超时检测是由参数设定的,如select,join,wait等
3.IO多路复用
1.定义:同时监控多个IO事件,当哪个IO事件准备就绪就执行哪个IO事件,形成并发效果
2.select模块(import select)
1.方法
1.select #支持win,linux,unix
1.原型:r,w,x = select(rlist,wlist,xlist,[timeout])
2.功能:监控IO事件,阻塞等待IO事件发生
3.参数:
1.rlist:列表 存放监控的等待处理的IO
2.wlist:列表 存放我们希望主动处理的IO
3.xlist:列表 存放如果发生异常需要处理的IO
4.timeout:数字 超时检测 可选参数,默认一直阻塞
4.返回值:
1.r:返回列表 rlist中准备就绪的IO
2.w:返回列表 wlist中准备就绪的IO
3.x:返回列表 xlist中准备就绪的IO
(乱七八糟,待用时再细看)2.poll #支持linux,unix
1.步骤:
1.创建poll对象:p=select.poll()
2.加入关注IO:p.register(s)
p.unregister(s) 从监控列表中删除
3.使用poll函数监控:events = p.poll()
功能:阻塞等待register的时间只要有任意准备就绪即返回
返回值:列表 events = [(fileno,evnet),(),()]
4.判断发生事件:s & POLLIN
5.处理发生的IO事件
2.poll 常用io事件(EVENTS)
1.POLLIN:相当于rlist
2.POLLOUT:相当于wlist
3.POLLUP:断开连接
4.POLLERR:相当于xlist
5.POLLPRI:紧急处理
6.POLLVAL:无效数据
3.epoll #支持linux,unix
1.特点
1.效率上比poll和select稍微高一点
2.只能用于linux,unix
3.支持边缘触发,select和poll只支持水平触发
3.注意点:
1.在处理IO过程中,不应发生死循环(某个IO单独占有服务器)
2.IO多路复用是单进程程序,是一个并发程序
3.IO多路复用有较高的IO执行效率

4.事件驱动IO
5.异步IO

本地套接字
1.linux文件种类
1. b 块设备文件
2. c 字符设备文件
3. d 文件夹
4. - 普通文件
5. l 连接文件
6. s 套接字文件
7. p 管道文件
2.本地套接字
1.意义:在linux/unix操作系统下,提供本地进程间通信的一种方式
2.创建流程:
1.创建套接字文件
2.绑定套接字文件
3.监听
4.接收连接
5.消息收发

知识点
1.发送接收缓冲区
1.发送和接收消息均线放到缓冲区再进行处理
2.recv接收消息,当一次接收不完的时候,下次会继续接收
3.当recv阻塞时,如果客户端断开,则recv立即返回空字符串

2.TCP粘包处理
1.定义:TCP中数据以数据流的方式发送接收,每次发送的数据间没有边界,在接收时可能造成数据的粘连即为粘包
2.处理:
1.每次发送消息结束为止加标志
2.发送的消息添加结构描述
3.当连续发送时每次发送有一个短暂延迟 sleep(0.1)

3.argv命令行传参
import sys
1.传入的参数都是字符串
2.空格分隔各个参数
3.sys.argv 自动收集命令行内容为一个列表,返回一个列表,第一个元素是命令本身
4.如果要使用本身带空格的参数,可以把参数用""括起来

4.TCP和UDP的区别
1.TCP传输数据使用字节流的方式传输,UDP是数据包
2.TCP会产生粘包现象,UDP不会
3.TCP对网络条件要求高,UDP更适合实时传输
4.TCP可以保证传输的可靠性,UDP则不保证
5.TCP使用listen accept保证连接性,UDP不需要
6.TCP收发消息使用recv send sendall,udp使用recvfrom sendto

5.模块中的属性名字含义(dir(模块名)
1.全部大写的名字:一般为变量,常量,标示量
2.前后带__的名字:内置方法
3.大驼峰的名字:模块里的类
4.全部小写:模块中的方法或属性

6.更专业的打印异常信息
import traceback
捕获后:
trancback.print_exc()

7.os.unlink("路径") or os.remove("路径")
功能:删除某个文件
参数:路径
os.path.exists("路径")
功能:判断一个文件是否存在
参数:路径
返回值:bool

2.socket编程的更多相关文章

  1. Linux下的C Socket编程 -- server端的继续研究

    Linux下的C Socket编程(四) 延长server的生命周期 在前面的一个个例子中,server在处理完一个连接后便会立即结束掉自己,然而这种server并不科学啊,server应该是能够一直 ...

  2. java socket编程(li)

    一.网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输.在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以 ...

  3. Python Socket 编程——聊天室示例程序

    上一篇 我们学习了简单的 Python TCP Socket 编程,通过分别写服务端和客户端的代码了解基本的 Python Socket 编程模型.本文再通过一个例子来加强一下对 Socket 编程的 ...

  4. Linux下的C Socket编程 -- server端的简单示例

    Linux下的C Socket编程(三) server端的简单示例 经过前面的client端的学习,我们已经知道了如何创建socket,所以接下来就是去绑定他到具体的一个端口上面去. 绑定socket ...

  5. Linux下的C Socket编程 -- 获取对方IP地址

    Linux下的C Socket编程(二) 获取域名对应的IP地址 经过上面的讨论,如果我们想要连接到远程的服务器,我们需要知道对方的IP地址,系统函数gethostbyname便能够实现这个目的.它能 ...

  6. Linux下的C Socket编程 -- 简介与client端的处理

    Linux下的C Socket编程(一) 介绍 Socket是进程间通信的方式之一,是进程间的通信.这里说的进程并不一定是在同一台机器上也有可能是通过网络连接的不同机器上.只要他们之间建立起了sock ...

  7. python网络编程-socket编程

     一.服务端和客户端 BS架构 (腾讯通软件:server+client) CS架构 (web网站) C/S架构与socket的关系: 我们学习socket就是为了完成C/S架构的开发 二.OSI七层 ...

  8. Socket编程实践(2) Socket API 与 简单例程

    在本篇文章中,先介绍一下Socket编程的一些API,然后利用这些API实现一个客户端-服务器模型的一个简单通信例程.该例子中,服务器接收到客户端的信息后,将信息重新发送给客户端. socket()函 ...

  9. Socket编程实践(1) 基本概念

    1. 什么是socket socket可以看成是用户进程与内核网络协议栈的编程接口.TCP/IP协议的底层部分已经被内核实现了,而应用层是用户需要实现的,这部分程序工作在用户空间.用户空间的程序需要通 ...

  10. [转]C语言SOCKET编程指南

    1.介绍 Socket编程让你沮丧吗?从man pages中很难得到有用的信息吗?你想跟上时代去编Internet相关的程序,但是为你在调用 connect() 前的bind() 的结构而不知所措?等 ...

随机推荐

  1. 面试官问PHP四大主流框架的优缺点,看这篇就够了!

    本篇文章我们来讲讲PHP四大框架的优缺点都有哪些,让你们在开发中更好的去选择使用哪款PHP框架去完成项目,废话不多说,我们一起来看看吧!! ThinkPHP ThinkPHP(FCS)是一个轻量级的中 ...

  2. 为Github的README.md生成目录的小工具

    1 概述 因为Github的README.md文件[TOC]不生效,因此封装了一个别人已封装好的JAR包供大家使用. 2 使用方法 用Java做的,只需要JDK11以上的环境: java -jar t ...

  3. C语言-内存函数的实现(二)之memmove

    C语言中的内存函数有如下这些 memcpy memmove memcmp memset 下面看看memmove函数 memmove 为什么会需要memmove函数? int main() { int ...

  4. forEach和map的用法和区别

    forEach()和map()都是处理数组的高阶函数有相同的三个值:(currentValue,index,arr): currentValue:必选,当前元素的值,index:可选,当前元素的下标, ...

  5. 5. Linux常用命令

    clear命令: 作用:清屏 快捷键:Ctrl + L pwd命令: 作用:用于显示当前的工作路径位置(当前工作文件夹) 示例: $ pwd /home/tarena Linux/Unix下的路径: ...

  6. 怎样用SQL修改某个字段的部分内容

    方法:update dede_addonarticle set body = replace(body,'#p#分页标题#e#',' ') where body like '%#p#分页标题#e#%'

  7. CVE-2013-3346:十全九美的 Adobe Reader ToolButton UAF 漏洞

    0x01 "Epic Turla" 网络间谍行动 在 2014 年 8 月,被誉为 "世界十大最危险的网络攻击行动" 之一的 "Epic Turla& ...

  8. java线程池实践

    线程池大家都很熟悉,无论是平时的业务开发还是框架中间件都会用到,大部分都是基于JDK线程池ThreadPoolExecutor做的封装, 都会牵涉到这几个核心参数的设置:核心线程数,等待(任务)队列, ...

  9. 【JavaScript】Leetcode每日一题-递增顺序搜索树

    [JavaScript]Leetcode每日一题-递增顺序搜索树 [题目描述] 给你一棵二叉搜索树,请你 按中序遍历 将其重新排列为一棵递增顺序搜索树,使树中最左边的节点成为树的根节点,并且每个节点没 ...

  10. 前端小白的学习之路html与css的较量【一】

    html和css的较量 web结构的组成 html标签规则 快速生成一个html html的基本结构 标签的关系 标签 标题标签 段落 图片 超链接 a 属性 a标签里面的值 字符实体 新增的标签 1 ...