python网络编程作用-Python进阶之网络编程

网络通信

使用网络的目的

把多方链接在一起,进行数据传递;

网络编程就是,让不同电脑上的软件进行数据传递,即进程间通信;

ip地址

ip地址概念和作用

IP地址是什么:比如192.168.1.1 这样的一些数字;

ip地址的作用:用来在电脑中 标识唯一一台电脑,比如192.168.1.1;在本地局域网是唯一的。

网卡信息

查看网卡信息

Linux:ifconfig

windows:ipconfig

ensxx:用来与外部进行通信的网卡;

lo:环回网卡,用来进行本地通信的;

linux关闭/开启网卡:sudo ifconfig ensxx down/up

ip和ip地址的分类

ip分为ipv4和ipv6

ip地址分为:

A类地址

B类地址

C类地址

D类地址--用于多播

E类地址--保留地址,因ipv6诞生,已无用

私有ip

单播--一对一

多播--一对多

广播--多对多

端口

ip:标识电脑;

端口:标识电脑上的进程(正在运行的程序);

ip和端口一起使用,唯一标识主机中的应用程序,进行统一软件的通信;

端口分类

知名端口

固定分配给特定进程的端口号,其他进程一般无法使用这个端口号;

小于1024的,大部分都是知名端口;

范围从0~1023;

动态端口

不固定分配,动态分配,使用后释放的端口号;

范围1024~65535;

socket

socket的概念

socket是进程间通信的一种方式,能实现不同主机间的进程间通信,即socket是用来网络通信必备的东西;

创建socket

创建套接字:

import socket

soc = socket.socket(AddressFamily, Type)

函数socket.socket创建一个socket,该函数有两个参数:

Address Family:可选 AF_INET(用于internet进程间通信)和AF_UNIX(用于同一台机器进程间通信);

Type:套接字类型,可选 SOCK_STREAM(流式套接字,主用于TCP协议)/SOCK_DGRAM(数据报套接字,主用于UDP套接字);

创建tcp套接字

import socket

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

...

soc.close()

创建udp套接字

import socket

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

...

soc.close()

udp

udp使用socket发送数据

在同一局域网内发消息;

如果用虚拟机和windows,要用桥接模式,确保在同一局域网内;

import socket

def main():

# 创建一个udp套接字

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

# 使用套接字收发数据

udp_socket.sendto(b"hahaha", ("193.168.77.1", 8080))

# 关闭套接字

udp_socket.close()

if __name__ == "__main__":

main()

udp发送数据的几种情况:

在固定数据的引号前加b,不能使用于用户自定义数据;

用户自定义数据,并进行发送,使用.encode("utf-8")进行encode编码

用户循环发送数据

用户循环发送数据并可以退出

只贴出最后一种情况,即完整代码

import socket

def main():

# 创建一个udp套接字

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

while 1:

# 从键盘获取要发送的数据

send_data = input("请输入你要发送的数据:")

if send_data == "exit":

break

# 使用套接字收发数据

udp_socket.sendto(send_data.encode("utf-8"), ("193.168.77.1", 8080))

# 关闭套接字

udp_socket.close()

if __name__ == "__main__":

main()

udp接收数据

接收到的数据是一个元组,元组第一部分是发送方发送的内容,元组第二部分是发送方的ip地址和端口号;

import socket

def main():

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

localaddr = ("", 8080)

udp_socket.bind(localaddr) # 必须绑定自己电脑的ip和端口

# 接收数据

recv_data = udp_socket.recvfrom(1024)

# recv_data这个变量存储的是一个元组,例如 (b"hahaha", ("192.168.77.1", 8888))

recv_msg = recv_data[0]

send_addr = recv_data[1]

# print("%s 发送了:%s" % (str(send_addr), recv_msg.decode("utf-8"))) # linux发送的数据用utf8解码

print("%s 发送了:%s" % (str(send_addr), recv_msg.decode("gbk"))) # windows发送的数据用gbk解码

udp_socket.close()

if __name__ == "__main__":

main()

udp接发数据总结

发送数据的流程:

创建套接字

发送数据

关闭套接字

接收数据的流程:

创建套接字

绑定本地自己的信息,ip和端口

接收数据

关闭套接字

端口绑定的问题

如果在你发送数据时,还没有绑定端口,那么操作系统就会随机给你分配一个端口,循环发送时用的是同一个端口;

也可以先绑定端口,再发送数据。

udp发送消息时自己绑定端口示例

import socket

def main():

# 创建一个udp套接字

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

# 绑定端口

udp_socket.bind(("192.168.13.1", 8080))

while 1:

# 从键盘获取要发送的数据

send_data = input("请输入你要发送的数据:")

if send_data == "exit":

break

# 使用套接字收发数据

udp_socket.sendto(send_data.encode("utf-8"), ("193.168.77.1", 8080))

# 关闭套接字

udp_socket.close() # 按ctrl+c退出

if __name__ == "__main__":

main()

但应注意,同一端口在同一时间不能被两个不同的程序同时使用;

单工,半双工,全双工

单工半双工全双工的理解

单工:

只能单向发送信息,别人接收,别人不能回复消息,比如广播;

半双工:

两个人都能发消息,但是在同一时间只能有一个人发消息,比如对讲机;

全双工:

两个人都能发消息,能同时发,比如打电话;

udp使用同一套接字收且发数据

"""socket套接字是全双工"""

import socket

def main():

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

udp_socket.bind(("192.168.13.1", 8080))

# 让用户输入要发送的ip地址和端口

dest_ip = input("请输入你要发送数据的ip地址:")

dest_port = int(input("请输入你要发送数据的端口号:"))

# 从键盘获取要发送的数据

send_data = input("请输入你要发送的数据:")

# 使用套接字收发数据

udp_socket.sendto(send_data.encode("utf-8"), (dest_ip, dest_port))

# 套接字可以同时 收发数据;

recv_data = udp_socket.recvfrom(1024)

print(recv_data)

# 关闭套接字

udp_socket.close() # 按ctrl+c退出

if __name__ == "__main__":

main()

在这里体现不出来socket是全双工,因为现在解释器只能按照流程,一步一步走下去,后面学习了进程线程协程就可以做到了。

tcp

tcp-可靠传输

tcp采取的机制

采用发送应答机制

超时重传

错误校验

流量控制和阻塞管理

tcp与udp的区别

tcp更安全可靠,udp相对没那么安全可靠;

面向连接

有序数据传输

重发丢失的数据

舍弃重复的数据包

无差错的数据传输

阻塞/流量控制

tcp,udp应用场景

tcp应用场景:下载,发送消息

udp应用场景:电话,视频直播等

tcp客户端

tcp客户端发送数据

import socket

def main():

# 1.创建tcp的套接字

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

# 2.链接服务器

tcp_socket.connect(("193.168.11.1", 8080))

# 3.发送/接收消息

send_data = input("请输入你要发送的消息:")

tcp_socket.send(send_data.encode("utf-8"))

# 4.关闭套接字

tcp_socket.close()

if __name__ == "__main__":

main()

tcp服务器

监听套接字,专门用来监听的;

accept会对应新创建的套接字,当监听套接字收到一个请求后,将该请求分配给新套接字,由此监听套接字可以继续去监听了,而新套接字则为该胡克段服务。

import socket

def main():

# 创建tcp套接字

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

tcp_service_socket.bind(("", 8080))

# 让默认的套接字由主动变为被动

tcp_service_socket.listen(128)

# 等待客户端的链接

new_client_socket, client_addr = tcp_service_socket.accept()

print("链接的客户端地址为:", client_addr)

# 接收客户端发送过来的请求

recv_data = new_client_socket.recvfrom(1024)

print(recv_data)

# 给客户端回送消息

new_client_socket.send("hahahah".encode("utf-8"))

new_client_socket.close()

tcp_service_socket.close()

if __name__ == "__main__":

main()

listen里面的参数,表示同时只允许128个链接访问。

QQ不绑定端口的运行原理-扩展

udp和tcp并用;

使用QQ,先登录,登录后告诉腾讯服务器此QQ运行的端口,发消息时,通过腾讯服务器转发给另一个QQ;

不绑定端口也有一个好处,就是允许多开,即一个电脑上可以运行多个QQ;

recv和recvfrom的区别

recvfrom里面不仅有发过来的数据,还有发过来数据的人的信息;

recv里面就只有数据;

tcp客户端服务端流程梳理

tcp服务器流程梳理

创建服务器套接字

绑定本地信息

让默认的套接字由主动变为被动

等待客户端的链接,堵塞

被客户端链接后,创建一个新的客服套接字为客户端服务;

接收客户端发送的消息,堵塞

接收客户端发送的消息后,给客户端回消息

关闭客服套接字,关闭服务端套接字

tcp注意点

tcp服务器一般情况下都需要綁定,否则客户端找不到这个服务器。

tcp客户端一般不绑定,因为是主动链接服务器,所以只要确定好服务器的ip, port等信息就好,本地客户端可以随机。

tcp服务器通过listen可以将socket创建出来的主动套接字变为被动的,这是做tcp服务器时必须要做的。

当客户端需要链接服务器时,就需要使用connect进行链接, udp是不需要链接的而是直接发送,但是tcp必须先链接,只有链接成功才能通信。

当一个tcp客户端连接服务器时,服务器端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务。

liston后的套接字是被动套接字,用来接收新的客户端的链接请求的,而accept返回的新套接字是标记这个新客户端的。

关闭isten后的套接字意味着被动套接字关闭了,会导致新的客户端不能够链接服务器,但是之前已经链接成功的客户端正常通信。

关闭accept返回的套接字意味着这个客户端已经服务完毕。

9.当客户端的套接字调用close后.服务器端会recv解堵塞,并且返回的长度为0,因此服务器可以通过 返回数据的长度来区别客户端是否已经下线。

tcp应用案例 ###

示例1-为一个用户办理一次业务:

"""可以理解为银行一个客服为排队的人员办理业务"""

import socket

def main():

# 1.创建tcp套接字

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

# 2.绑定本地信息

tcp_service_socket.bind(("", 8080))

# 3.让默认的套接字由主动变为被动

tcp_service_socket.listen(128)

while 1:

# 4.等待客户端的链接

new_client_socket, client_addr = tcp_service_socket.accept()

print("链接的客户端地址为:", client_addr)

# 接收客户端发送过来的请求

recv_data = new_client_socket.recvfrom(1024)

print(recv_data)

# 给客户端回送消息

new_client_socket.send("hahahah".encode("utf-8"))

# 关闭套接字

new_client_socket.close()

tcp_service_socket.close()

if __name__ == "__main__":

main()

示例2-为同一用户服务多次并判断一个用户是否服务完毕:

"""可以理解为银行一个客服为排队的人员办理业务"""

import socket

def main():

# 1.创建tcp套接字

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

# 2.绑定本地信息

tcp_service_socket.bind(("", 8080))

# 3.让默认的套接字由主动变为被动

tcp_service_socket.listen(128)

while 1:

# 4.等待客户端的链接

new_client_socket, client_addr = tcp_service_socket.accept()

print("链接的客户端地址为:", client_addr)

# 循环目的:为同一个客户服务多次

while 1:

# 接收客户端发送过来的请求

recv_data = new_client_socket.recvfrom(1024)

print(recv_data)

# 如果recv解堵塞,那么有两种方式

# 1.客户端发了数据过来

# 2.客户端调用了close

if recv_data:

# 给客户端回送消息

new_client_socket.send("hahahah".encode("utf-8"))

else:

break

# 关闭套接字

new_client_socket.close()

tcp_service_socket.close()

if __name__ == "__main__":

main()

示例3-tcp文件下载客户端和服务端:

文件下载客户端

import socket

def main():

# 1.创建套接字

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

# 2.获取服务器的ip,port

dest_ip = input("请输入你要链接的服务器ip:")

dest_port = input("请输入你要链接的端口:")

# 3.链接服务器

tcp_socket.connect((dest_ip, dest_port))

# 4.获取下载的文件名字

want_file = input("请输入你要下载的文件:")

# 5.将文件名字发送到服务器

tcp_socket.send(want_file.encode("utf-8"))

# 6.接收要下载的文件

file_data = tcp_socket.recv(1024)

# 7.将接收文件的数据写入一个文件中

if file_data:

with open("[复件]" + want_file, "wb") as f:

f.write(file_data)

# 8.关闭套接字

tcp_socket.close()

pass

if __name__ == "__main__":

main()

文件下载服务端

import socket

def send_file2client(new_socket, client_addr):

# 1.接受客户端发送过来的 要下载的文件名

want_file = new_socket.recv(1024).decode("utf-8")

print("客户端 %s 要接收的文件为:%s" % (str(client_addr), want_file))

# 2.读取文件数据

file_data = None

try:

f = open(want_file, "rb")

file_data = f.read()

f.close()

except Exception as e:

print("你要下载的文件 %s 不存在" % want_file)

# 3.发送文件的数据给客户端

if file_data:

new_socket.send(file_data)

def main():

# 1.创建套接字

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

# 2.绑定本地信息

tcp_socket.bind(("", 8080))

# 3.套接字被动接受 listen

tcp_socket.listen(128)

while 1:

# 4.等待客户端的链接 accept

new_socket, client_addr = tcp_socket.accept()

# 5.调用函数发送文件到客户端

send_file2client(new_socket, client_addr)

# 7.关闭套接字

new_socket.close()

tcp_socket.close()

if __name__ == "__main__":

main()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值