千家信息网

10.python网络编程(startin part 1)

发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,一.什么是socket?socket就是为了实现C/S架构而生的,socket位于应用层和传输层之间,是传输层和应用层之间的一组接口,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说
千家信息网最后更新 2025年01月23日10.python网络编程(startin part 1)

一.什么是socket?

socket就是为了实现C/S架构而生的,socket位于应用层和传输层之间,是传输层和应用层之间的一组接口,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议,所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。

也有人将socket说成ip+port,ip是用来标识互联网中的一台主机的位置,而port是用来标识这台机器上的一个应用程序,ip地址是配置到网卡上的,而port是应用程序开启的,ip与port的绑定就标识了互联网中独一无二的一个应用程序。

补充:有人会把socket和程序的pid弄混,程序的pid是同一台机器上不同进程或者线程的标识。


二.socket种类。

  1. 基于文件型套接字。

    AF_UNIX:基于文件型的套接字,就是通过底层的文件系统来取数据,两个套接字进程运行在同一台机器,可以通过访问同一个文件系统来实现两个程序之间的通信。

  2. 基于网络型套接字。

三.socket工作流程。

tcp服务端建立连接流程:

socket()实例化出一个套接字对象→bind()绑定ip地址和端口→listen()开始监听之前绑定的ip地址和端口→accept()开始被动接收tcp客户端发来的连接,会一直等连接的到来(如果没有连接,就会一直等,直到有客户端连过来。

tcp客户端建立连接流程:

socket()客户端也初始化一个套接字对象→connect()主动去连接服务端(主动初始化与tcp服务器的连接)如果连接成功,客户端和服务器之间就可以互相收发数据了。(其实connect就相当于去回应服务端的accept,服务端的accept一直在等待客户端去connect)

客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。



四.socket模块的用法。

import socket

socket.socket(socket_family,socket_type,protocal=0)

socket_family 可以是 AF_UNIX 或 AF_INET。socket_type 可以是 SOCK_STREAM 或 SOCK_DGRAM。protocol 一般不填,默认值为 0。

获取tcp/ip套接字

tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

获取udp/ip套接字

udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

由于 socket 模块中有太多的属性。我们在这里破例使用了'from module import *'语句。使用 'from socket import *',我们就把 socket 模块里的所有属性都带到我们的命名空间里了,这样能 大幅减短我们的代码。

例如tcpSock = socket(AF_INET, SOCK_STREAM)


服务端常用专属套接字方法:

s.bind():绑定(主机,端口号)到套接字。

s.listen():开始进行tcp监听。#listen方法中可以指定一个backlog参数,这个参数用于设置tcp连接池的大小(关于tcp连接池和三次握手的知识后面会做补充。)

s.accept():被动接受TCP客户的连接,(阻塞式)等待连接的到来。


客户端常用专属套接字方法:

s.connect():主动初始化TCP服务器连接

s.connect_ex() : connect()函数的扩展版本,出错时返回出错码,而不是抛出异常。


客户端和服务端共同具有的常用套接字方法:

s.recv():接收tcp数据。#需要指定每次收多少字节。

s.send(): 发送tcp数据,#发送TCP数据(send在待发送数据量大于对端缓存区剩余空间时,数据丢失,不会发完)

s.sendall(): 发送tcp数据,发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于对端缓存区剩余空间时,数据不丢失,循环调用send直到发完)(个人分析,本质上是调用了循环)

s.recvfrom():接收UDP数据

s.sendto() : 发送UDP数据

s.getpeername() : 连接到当前套接字的远端的地址

s.getsockname() : 当前套接字的地址

s.getsockopt() :返回指定套接字的参数

s.setsockopt() : 设置指定套接字的参数

s.close() :关闭套接字


五.socket用法示例。

服务端:

#!/usr/bin/python2.7

# -*- coding:utf-8 -*-

import socket

address_and_port = ('127.0.0.1',8888)

s1 = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)

s1.bind(address_and_port)

s1.listen(3)

conn,addr = s1.accept() #执行了socket的accept方法后,开始阻塞,等待客户端的连接.

#执行了accept方法后,会返回一个元祖,这个元祖里面包含了一个客户端的连接对象,还有客户端的ip地址和端口.

while True:

data = conn.recv(1024) #用于接收tcp数据,后面的1024表示,recv一次最多可以接收1024字节.(执行到recv,如果对端没有发来数据,或者内容为空,程序会阻塞住,不继续向下执行。)

print data

conn.send(data.upper())

conn.close() #关闭与客户端的连接

s1.close() #关闭服务端套接字连接


客户端:

#!/usr/bin/python2.7

# -*- coding:utf-8 -*-

import socket

s1 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s1.connect(('127.0.0.1',8888))

while True:

msg = raw_input(">>>").strip()

s1.send(msg.encode(('utf-8')))

print "客户端已发送数据!"

data = s1.recv(1024)

print data

#上面两个代码,可以简单理解下socket的工作流程。


六.解决sockt 通信客户端断开服务端崩溃等问题的解决方法(连接循环,通信循环,以及异常捕捉)

服务端:

#!/usr/bin/python2.7

# -*- coding:utf-8 -*-

import socket

address_and_port = ('127.0.0.1',8888)

s1 = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)

s1.bind(address_and_port)

s1.listen(3)

while True: #此处问连接循环,会循环等连接。

conn,addr = s1.accept() #执行了socket的accept方法后,开始阻塞,等待客户端的连接.

#执行了accept方法后,会返回一个元祖,这个元祖里面包含了一个客户端的连接对象,还有客户端的ip地址和端口.

while True: #数据传输循环

try: #防止客户端断开导致的服务断抛异常。

data = conn.recv(1024) #用于接收tcp数据,后面的1024表示,recv一次最多可以接收1024字节.

if not data:

break

print data

conn.send(data.upper())

except Exception:

break

conn.close() #关闭与客户端的连接

s1.close() #关闭服务端套接字连接


客户端:

#!/usr/bin/python2.7

# -*- coding:utf-8 -*-

import socket

s1 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s1.connect(('127.0.0.1',8888))

while True:

msg = raw_input(">>>").strip()

if not msg: #防止客户端发送空数据

continue

s1.send(msg.encode(('utf-8')))

print "客户端已发送数据!"

data = s1.recv(1024)

print data

s1.close()


#以上是防止服务端崩溃的一些解决方法。






七.关于udp套接字。

服务端大概操作流程:

ss = socket() #创建一个服务器的套接字

ss.bind() #绑定服务器套接字

inf_loop: #服务器无限循环

cs = ss.recvfrom()/ss.sendto() # 对话(接收与发送)

ss.close() # 关闭服务器套接字



客户端大概的操作流程:

cs = socket() # 创建客户套接字

comm_loop: # 通讯循环

cs.sendto()/cs.recvfrom() # 对话(发送/接收)

cs.close() # 关闭客户套接字


下面是udp套接字的一个简单的示例:

示例1:

服务端:

import socket

udp_server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

udp_server.bind(('127.0.0.1',8888))

while True:

msg,addr = udp_server.recvfrom(1024)

print msg ,addr

udp_server.sendto(msg.upper(),addr)


客户端:

import socket

udp_client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

while True:

msg = raw_input(">>:").strip()

if not msg:

continue

udp_client.sendto(msg.encode('utf-8'),("127.0.0.1",8888))

back_msg,addr = udp_client.recvfrom(1024)

print back_msg.decode('utf-8') ,addr



八.关于tcp套接字和udp套接字你需要知道的。

  1. 首先有几点必须明确!

    1.1 所有的收发消息,都是在操作自己的tcp/udp缓冲区,发消息是将数据发送到自己的缓冲区中,收消息同样也是从缓冲区中收取。

    1.2 tcp 使用send发消息,使用recv收消息

    1.3udp 使用sendto发消息,使用recvfrom收消息

  2. tcp与udp

    2.1 tcp是基于流的,udp是基于报的

2.2 使用send发送数据流的时候,若数据流为空,那么tcp buffer(缓冲区)也为空,操作系统不会控制tcp发包。

sendinto(bytes_data,ip_port):发送数据报,bytes_data为空,还有ip_port,所有即便是发送空的bytes_data,数据报其实也不是空的,自己这端的缓冲区收到内容,操作系统就会控制udp协议发包。

3.关于tcp的补充

tcp基于链接通信:

基于链接,则需要listen(backlog),指定半连接池的大小

基于链接,必须先运行的服务端,然后客户端发起链接请求

对于mac系统:如果一端断开了链接,那另外一端的链接也跟着完蛋recv将不会阻塞,收到的是空(解 决方法是:服务端在收消息后加上if判断,空消息就break掉通信循环)

对于windows/linux系统:如果一端断开了链接,那另外一端的链接也跟着完蛋recv将不会阻塞,收到 的是空(解决方法是:服务端通信循环内加异常处理,捕捉到异常后就break掉通讯循环)


udp通信。

无链接,因而无需listen(backlog),更加没有什么连接池之说了

无链接,udp的sendinto不用管是否有一个正在运行的服务端,可以己端一个劲的发消息,只不过数据丢失

recvfrom收的数据小于sendinto发送的数据时,在mac和linux系统上数据直接丢失,在windows系统上发送的比接收的大直接报错

只有sendinto发送数据没有recvfrom收数据,数据丢失。


注意:

1.你单独运行上面的udp的客户端,你发现并不会报错,相反tcp却会报错,因为udp协议只负责把包发出去,对方收不收,我根本不管,而tcp是基于链接的,必须有一个服务端先运行着,客户端去跟服务端建立链接然后依托于链接才能传递消息,任何一方试图把链接摧毁都会导致对方程序的崩溃。

2.上面的udp程序,你注释任何一条客户端的sendinto,服务端都会卡住,为什么?因为服务端有几个recvfrom就要对应几个sendinto,哪怕是sendinto(b'')那也要有。


数据 客户 服务 套接字 客户端 端的 链接 循环 方法 消息 程序 服务器 系统 地址 通信 流程 阻塞 就是 缓冲区 应用 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 网络安全等级保护备案流程 互联网云科技ppt 个人网络安全分析 数据库mysql8.0 服务器宝塔面板切换成小皮面板 关于制定软件开发计划的说法 服务器最便宜多少钱一年 广州博瑞互联网科技有限公司 法庭说话人识别语音数据库的构建 幻塔白月破晓服务器是官服吗 网络安全在我心中主题班会 大练兵网络安全专题教育 wincc查询数据库脚本 联想服务器怎么打开机箱盖 音乐软件开发产品经理 学游戏软件开发需要考什么证 数据库导出报错00028 游戏服务器哪个性能好 守护网络安全我们应该这么做 规范网络安全运行管理 ip广播系统服务器 网络安全周这几个字图片 软件开发中的作用和意义 数据库原理与技术有什么用 灵钰网络技术有限公司 公司数据库开发目标 收录医学文献的数据库有哪些 南职物联网网络技术专业 access数据库排版 南京亘远网络技术有限公司
0