基于底层的tcp,udp编程,高层的应用层,http编程
底层的效率高,tcp可以保证数据库安全,效率高
socket(插座),网络编程,是点对点,每一个就是一个孔,中间链接起来,socket简单来讲就是端到端的编程,端对端,建立一个网络通讯的通道,从socket到scoket,从一个插座到另一个插座,建立一个数据通讯的通道
python也提高了socket.py的模块,是低级的网络编程接口,统一的socket编程接口,所有操作系统通用
进程间通讯IPC,远程调用RPC,最底层还需要socket开始
socket掌握TCP有链接协议,UDP无链接协议即可
UDP协议好处是短小,效率高,不保证数据发送出去有没有人收到
tcp和UDP编程都是端到端
所谓的C/S编程就是server,和client如何通讯
早期的QQ聊天是需要你选择服务器才可以使用的,只不过现在屏蔽了
client和server是用功能来分,其实是双向的,数据可以来回,一般把功能强大的,都链接指向的称为server,与它链接的称为client
TCP的server端比较麻烦,首先需要创建socket对象,
路由管的是IP,到达应用层区分才靠端口。路由到通讯的主机,询问,这个IP上面的对应的端口,比如IP地址对应的TCP 8000是否有进程占用。
资源是分给进程的,所以线程是共享这个资源。
一个应用程序要用网络,必须开一个socket,告诉别人是用上面协议的,地址端口
默认都指tcp的,所以只要绑定IP和端口即可,一旦某个应用程序绑定了某个协议和端口之后,其他程序不你能再对这个端口占用
绑定只是把端口给你用了,还买开始工作,工作就需要监听端口,listen(),
accepct()允许,会把链接过来的client分配一个新的socket,这样就服务器可以和客户端传输数据了
recv(),client发来的东西,server 接收
client接受,就需要调用send()方法
server端,创建socket,做地址端口绑定,监听端口,然就accept。
client通过这个IP地址协议。链接端口,建立链接后。
TCP server 分配一个新的socket,client的读写和这个tcp server的新的socket进行读写操作。
tcp server 端有socket和一个新的socket,这点是比较麻烦的
socket用完之后,因为会占用文件描述符,用完就可以关闭
这里其实server端,accept以后会创建一个新的socket出来,客户端的通讯是和这个新的socket进行通讯的,原来的server 的socket是在接收新的客户端链接,
每一个链接其实都要建立一个socket
每一个链接其实就要一个socket,
实验
协议已经写了 AF_INET (ipv4) SOCK_STREAM (tcp)
windows 和linux都有网络命令,
linux 用 ss -tanl (t=tcp,a=all,n=端口数字 ,l=listen)
windows 用netstat -anp tcp
用管道找listen的端口
加断点走到bind结束了
现在还是没有监听端口的,没有监听之前是看不到端口的
F8继续往下走
现在就有了
加上b,是显示哪个进程的
现在还没退出,到这里,阻塞等待client链接
用这个程序
链接一下就断掉了
用的端口是50139
打印的c是打印出了一个元组
l代表local,r代表远端,本地在9999,远程地址在50139
accpet一旦连接成功会生成一个新的socket
现在读写是要靠新的socket
server一般被动接收数据,使用recv,现在就卡在accept上等待链接
这样就收到数据了,然后就close了
decode英文意思是 解码,输出是字符串,encode英文原意 编码输出是bytes
socket原始传输的是bytes,否则出错
socket最原始接口得到的是bytes
**tcp只有三次链接accept之后,创建新的socket,这个新的socket,是被accept的返回值带回来的,是对端的端口,这样就可以和client完成端到端的通讯,
**
注意:一般recv是在等待数据到来,等待new socket的里面缓冲区有数据
send是发数据,这个new socket可以单独关闭
同时多个client链接就是高并发,网络IO的高并发
端口只能绑定一次
接收另一个的链接,下面的s2还可以recv和send
先发送一个
再创建一个 链接
现在就两个链接创建了
现在走到35行阻塞
发送也就断开了
之前的发送数据,已经处于假死的状态,socket已经关闭了,但是好处是,再次链接,因为放在缓冲区里,就给你发送出去了
这样就是互相干扰,避免这种阻塞互相干扰,可以利用多线程
查看监听端口的两种方式
练习写一个群聊程序
互相能看到发的数据
服务器端应该accept链接,每一个client链接以后要甩出一个new socket进行通信,recv到一个用户的信息,分发给不同的客户端,
停止服务
记录链接的客户端
写代码就是封装函数和类,先设计类ChatServer,start启动服务,accept接收链接,recv接收数据,stop停止服务
0.0.0.0代表本地所有IP地址,127.0.0.1自身
可以用logging打印一下
现在可以使用,只要创建实例,start之后到accept卡住
现在一个线程用起来还可以
tcp是知道对端的,laddr,raddr,socket里面都有这些信息
这样就可以重复发数据了
但是创建另外的链接就没有回来的数据,只有发送的数据
每一次链接的时候都需要一个accept等待,才能链接上来
我们现在这么写的是不可以的
accept返回之后还要再new一个出来,但是现在的self。recv会进入下面的死循环,轮不到上面语句执行
多线程试试
这样就可以了
现在有两个客户端链接就是两个线程,还有一个主线程,总共三个线程
这一句会导致主线程阻塞
主线程不阻塞了,一执行就直接关闭了
现在可以观察线程的工作方式
运行,现在就一个accept在跑
链接发送消息
敲回车,就有新的线程了
再次链接发送消息
现在就有两个线程了
主动断开现在会产生一个异常出来,把r-x线程崩溃,跟主线程无关
少了一个r-1
主线程往往是用来管理的,工作线程是用来工作与通讯的
到此为止,点对点的网络通讯 程序就完成了
面试写一个socket通讯,至少写成这样,多线程有,面向对象也有
来源:CSDN
作者:PX小葵
链接:https://blog.csdn.net/qq_42227818/article/details/103955544