8.7 day28 网络编程 sockt套接字

sockt 套接字

套接字主要有两个版本,一个是基于文件类型的套接字家族(AF_UNIX),一个是基于网络类型的套接字家族(AF_INET)。这里介绍的是后者。

使用了socket以后,你就只需要专注于应用层的设计编写。涉及到与其他层交互,只需要调用socket套接字就行。

服务端

import socket


server = socket.socket()  # 买手机 不传参数默认用的就是TCP协议
server.bind(('127.0.0.1',8080))  
# bind()里面要放address,只靠IP是不能确定唯一的位置的,还需要port
# 需要在一个位置传两个参数,所以传进去的形式得是一个元组
# bind((host,port))  插电话卡  绑定ip和端口
server.listen(5)  # 开机    半连接池


conn, addr = server.accept()  # 接听电话  等着别人给你打电话     阻塞
data = conn.recv(1024)  # 听别人说话 接收1024个字节数据          阻塞
print(data)
conn.send(b'hello back')  # 给别人回话 
conn.close()  # 挂电话
server.close()  # 关机

客户端

import socket


client = socket.socket()  # 拿电话
client.connect(('127.0.0.1',8080))  # 拨号   写的是对方的ip和port

client.send(b'hello stranger')  # 对别人说话
data = client.recv(1024)  # 听别人说话
print(data)
client.close()  # 挂电话

先运行 服务端 ,然后运行 客户端

服务端:b'hello stranger'

客户端:b'hello back'

127.0.0.1是本机回还地址,只能自己识别自己,其他人无法访问

TCP协议相当于打电话

send与recv对应

扫描二维码关注公众号,回复: 6976706 查看本文章

​ 不要出现两边都是相同的情况

​ recv是跟内存要数据,send发数据也是发到内存

​ 至于数据的来源,你无需考虑

注意:

如果遇到以下问题(尤其是Mac用户)

需要在以下位置加上这两句

from socket import SOL_SOCKET,SO_REUSEADDR

server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)

python 通过 socket 发送文件的实例代码

目录结构:

client:

#!/usr/bin/env python
# -*-coding:utf-8 -*-
import socket, struct, json
download_dir = r'D:\Python\python_learning\gd\code\part3\02网络编程\文件传输\client\download'
gd_client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
gd_client.connect(('127.0.0.1',8200))

while True:

#1、发命令
  cmd=input('>>: ').strip() #get a.txt
  if not cmd:continue
  gd_client.send(cmd.encode('utf-8'))
  #2、以写的方式打开一个新文件,接收服务端发来的文件的内容写入客户的新文件
  #第一步:先收报头的长度
  obj=gd_client.recv(4)
  header_size=struct.unpack('i',obj)[0]
  # 第二步:再收报头
  header_bytes = gd_client.recv(header_size)
  # 第三步:从报头中解析出对真实数据的描述信息
  header_json = header_bytes.decode('utf-8')
  header_dic = json.loads(header_json)
  '''
  header_dic = {
    'filename': filename, # 1.txt
    'file_size': os.path.getsize(r'%s\%s' % (share_dir, filename)) # 路径/1.txt
  }  
  '''
  total_size = header_dic['file_size']
  file_name = header_dic['filename']
  # 第四步:接收真实的数据
  with open(r'%s\%s'%(download_dir, file_name),'wb') as f:
    recv_size = 0
    while recv_size < total_size:
      line = gd_client.recv(1024)
      f.write(line)
      recv_size += len(line)
      print('总大小:%s  已下载大小:%s' % (total_size, recv_size))
gd_client.close()

server:

#!/usr/bin/env python
# -*-coding:utf-8 -*-
import socket
import subprocess
import struct
import json
import os
share_dir = r'D:\Python\python_learning\gd\code\part3\02网络编程\文件传输\server\share'
gd_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
gd_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
gd_server.bind(('127.0.0.1', 8200)) # 0-65535: 0-1024给操作系统使用
gd_server.listen(5)
while True:
  conn, client_addr = gd_server.accept()
  while True: # 通信循环
    try:
      # 1、收命令
      res = conn.recv(8096) # b'get 1.txt'
      if not res: break # 适用于linux操作系统
      # 2、解析命令,提取相应命令参数
      cmds = res.decode('utf-8').split() # ['get','1.txt']
      filename = cmds[1]
      # 3、以读的方式打开文件,读取文件内容发送给客户端
      # 第一步:制作固定长度的报头
      header_dic = {
        'filename': filename, # 1.txt
        'file_size':os.path.getsize(r'%s\%s'%(share_dir, filename)) # 路径/1.txt
      }
      header_json = json.dumps(header_dic)
      header_bytes = header_json.encode('utf-8')
      # 第二步:先发送报头的长度
      conn.send(struct.pack('i',len(header_bytes)))
      # 第三步:再发报头
      conn.send(header_bytes)
      # 第四步:再发送真实的数据
      with open('%s/%s'%(share_dir, filename),'rb') as f:
        for line in f:
          conn.send(line)
    except ConnectionResetError: # 适用于windows操作系统
      break
  conn.close()
gd_server.close()

命令输入: get 1.txt ,然后即可将 server 端的 share文件内的 1.txt 文件 发送到 client 端的 download文件夹下

图片、视频、文字都可以发送,因为传送的是 二进制文件

原理是:server 端以读的形式打开文件,client端以写 的方式打开文件,然后client端把 一条一条的二进制写入文件后保存即可。

猜你喜欢

转载自www.cnblogs.com/PowerTips/p/11318545.html
8.7