python网络编程socket编程_Python网络编程—socket套接字编程(TCP)

套接字介绍

1.套接字 : 实现网络编程进行数据传输的一种技术手段

2.Python实现套接字编程:import socket

3.套接字分类

流式套接字(SOCK_STREAM): 以字节流方式传输数据,实现tcp网络传输方案。(面向连接--tcp协议--可靠的--流式套接字)

数据报套接字(SOCK_DGRAM):以数据报形式传输数据,实现udp网络传输方案。(无连接--udp协议--不可靠--数据报套接字)

tcp套接字

服务端流程

1672612-20190607185004504-108993090.png

1.创建套接字

sockfd=socket.socket(socket_family=AF_INET,socket_type=SOCK_STREAM,proto=0)

功能:创建套接字

参数: socket_family 网络地址类型 AF_INET表示ipv4

socket_type 套接字类型 SOCK_STREAM(流式) SOCK_DGRAM(数据报)

proto 通常为0 选择子协议

返回值: 套接字对象

2.绑定地址

本地地址 : 'localhost' , '127.0.0.1'

网络地址 : '172.40.91.185'

自动获取地址: '0.0.0.0'

sockfd.bind(addr)

功能: 绑定本机网络地址

参数: 二元元组 (ip,port) ('0.0.0.0',8888)

1672612-20190607185131168-1142016454.png

3.设置监听

sockfd.listen(n)

功能 : 将套接字设置为监听套接字,确定监听队列大小

参数 : 监听队列大小

4.等待处理客户端连接请求

connfd,addr = sockfd.accept()

功能: 阻塞等待处理客户端请求

返回值: connfd 客户端连接套接字

addr 连接的客户端地址

5.消息收发

data = connfd.recv(buffersize)

功能 : 接受客户端消息

参数 :每次最多接收消息的大小

返回值: 接收到的内容

n = connfd.send(data)

功能 : 发送消息

参数 :要发送的内容 bytes格式

返回值: 发送的字节数

6.关闭套接字

sockfd.close()

功能:关闭套接字

ContractedBlock.giftcp服务端流程

客户端流程

1672612-20190607185931717-2041129319.png

1.创建套接字

注意:只有相同类型的套接字才能进行通信

2.请求连接

sockfd.connect(server_addr)

功能:连接服务器

参数:元组 服务器地址

3.收发消息

注意: 防止两端都阻塞,recv send要配合

4.关闭套接字

ContractedBlock.gif

ExpandedBlockStart.gif

1 """

2 重点代码3 """

4

5 from socket import *

6

7 #创建tcp套接字

8 sockfd = socket() #参数默认即tcp套接字

9

10 #连接服务端程序

11 server_addr = ("172.40.91.150",8888) #服务端地址

12 sockfd.connect(server_addr)13

14 whileTrue:15 #消息发送接收

16 data = input("Msg>>")17 #如果直接回车,则跳出循环

18 if notdata:19 break

20 sockfd.send(data.encode()) #转换字节串发送

21 data = sockfd.recv(1024)22 print("Server:",data.decode())23

24 sockfd.close()

tcp客户端流程

tcp 套接字数据传输特点

tcp连接中当一端退出,另一端如果阻塞在recv,此时recv会立即返回一个空字串。

tcp连接中如果一端已经不存在,仍然试图通过send发送则会产生BrokenPipeError

一个监听套接字可以同时连接多个客户端,也能够重复被连接

网络收发缓冲区

网络缓冲区有效的协调了消息的收发速度

send和recv实际是向缓冲区发送接收消息,当缓冲区不为空recv就不会阻塞。

tcp粘包

代码示例:day2/stick_send.py,stick_recv.py

原因:tcp以字节流方式传输,没有消息边界。多次发送的消息被一次接收,此时就会形成粘包。

影响:如果每次发送内容是一个独立的含义,需要接收端独立解析此时粘包会有影响。

处理方法:

人为的添加消息边界

控制发送速度

ContractedBlock.gif

ExpandedBlockStart.gif

1 from socket import *

2

3

4 sockfd =socket()5

6 server_addr = ("172.40.91.150",8888)7 sockfd.connect(server_addr)8

9 whileTrue:10 sockfd.send(b'hello')11

12 sockfd.close()

tcp 粘包

ContractedBlock.gif

ExpandedBlockStart.gif

1 importsocket2

3 sockfd =socket.socket(socket.AF_INET,4 socket.SOCK_STREAM)5 sockfd.bind(('0.0.0.0', 8888))6

7 sockfd.listen(3)8

9 whileTrue:10 print("Waiting for connect ...")11 connfd, addr =sockfd.accept()12 print("Connect from", addr)13

14 n =015 while n < 10:16 n += 1

17 data = connfd.recv(5)18 print(data)19

20 connfd.close() #断开连接

21

22 #关闭套接字

23 sockfd.close()

tcp粘包问题

练习:将一个文件从客户端发送到服务端,要求文件类型随意.

思路:读取文件--> send发送 recv接收--> write写入

ContractedBlock.gif

ExpandedBlockStart.gif

1 from socket import *

2 importtime3 #读取文件--> send发送

4 s =socket()5 s.connect(('127.0.0.1',8888))6

7 f = open('img.jpg','rb')8

9 #读取内容,将其发送

10 whileTrue:11 data = f.read(1024)12 if notdata:13 time.sleep(0.1)14 s.send(b'##')15 break

16 s.send(data)17

18 time.sleep(0.1)19 s.send("发送完毕".encode())20

21 f.close()22 s.close()23 ---------------------------------------------

24 from socket import *

25

26 s =socket()27 s.bind(('0.0.0.0',8888))28 s.listen(3)29

30 c,addr =s.accept()31 print("Connect from",addr)32

33 #以二进制写入

34 f = open('mm.jpg','wb')35

36 #循环接收内容,写入文件

37 whileTrue:38 #recv接收--> write写入

39 data = c.recv(1024)40 if data == b'##':41 break

42 f.write(data)43

44 data = c.recv(1024)45 print(data.decode())46

47 f.close()48 c.close()49 s.close()

练习

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值