socket编程

socket实现文件上传和下载

#!/usr/bin/env python
# coding:utf-8
import socket
import struct
import json
buffer = 1024
sk = socket.socket()
sk.bind(('127.0.0.1',8888))
sk.listen()
conn,addr = sk.accept()
ret = conn.recv(4)
len_operate_c = struct.unpack('i',ret)[0]
operate_c = conn.recv(len_operate_c)
operate_c = operate_c.decode('utf-8')
if operate_c == 'upload':
    res = conn.recv(4)
    len_head = struct.unpack('i',res)[0]
    head = conn.recv(len_head).decode('utf-8')
    head = json.loads(head)
    filesize = head['filesize']
    filename = head['filename']
    with  open (filename,'wb') as  f:
        while filesize:
            if filesize >= buffer:
                content = conn.recv(buffer)
                f.write(content)
                filesize -= buffer
            else :
                content = conn.recv(filesize)
                f.write(content)
                filesize = 0
conn.close()
sk.close()
server端
#!/usr/bin/env python
# coding:utf-8
def get_filename(file_path):
    return os.path.basename(file_path)
import socket
import os
import json
import struct
buffer = 1024
sk = socket.socket()
sk.connect(('127.0.0.1',8888))
operate = ['download','upload']
for  k,j  in  enumerate(operate,1) :
    print(k,j)
num = int(input('请输入你的选项: '))
operate_c = operate[(num-1)]
len_operate_c = len(operate_c)
print(len_operate_c)
res = struct.pack('i',len_operate_c)
sk.send(res)
sk.send(operate_c.encode('utf-8'))
if operate_c == 'upload' :
    head = {'filename':None,'filesize':None,}
    file_path = input("请输入要上传的文件绝对路径 :")
    filename = get_filename(file_path)
    head['filename'] = filename
    filesize = os.path.getsize(file_path)
    head['filesize']=filesize
    json_head = json.dumps(head)
    len_head = len(json_head)
    ret = struct.pack('i',len_head)
    sk.send(ret)
    sk.send(json_head.encode('utf-8'))
    with open (file_path,'rb') as f:
        while filesize:
            if filesize >= buffer :
                content =  f.read(buffer)
                sk.send(content)
                filesize -= buffer
            else :
                content = f.read(filesize)
                sk.send(content)
                filesize = 0
sk.close()
client端

 网络编程:实现不同机器上的程序通信

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

基于TCP简单socket通信

server端

import  socket
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
conn,addr = sk.accept()
ret = conn.recv(1024)
conn.send(b'hi')
print(ret)
conn.close()
sk.close()

 client端

 
 
import  socket
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
sk.send(b'hello')
res = sk.recv(1024)
print(res)
sk.close()
 
 

 服务端长连接

socket端

import  socket
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
# conn,addr = sk.accept()
while 1:
    conn,addr = sk.accept()
    ret = conn.recv(1024)
    ret = ret.decode('utf-8')
    if ret:
        conn.send(b'hi')
        print(ret)
server

client端

import  socket
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
sk.send(bytes('你好',encoding='utf8'))
res = sk.recv(1024)
print(res)
sk.close()
client
sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sk = socket.socket(family=AF_INET,type=SOCK_STREAM,proto=0,fileno=None)


参数一:地址簇

    socket.AF_INET IPv4(默认)
    socket.AF_INET6 IPv6

    socket.AF_UNIX 只能够用于单一的Unix系统进程间通信

  参数二:类型

    socket.SOCK_STREAM  流式socket , for TCP (默认)
    socket.SOCK_DGRAM   数据报式socket , for UDP

基于UDP简单socket通信

import  socket
sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sk.bind(('127.0.0.1',8080))
msg,(host,port) = sk.recvfrom(1024)
print(msg)
sk.sendto(b'hello',(host,port))
sk.close()
UDPserver
import  socket
sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
ip_port=('127.0.0.1',8080)
sk.sendto(b'hi',ip_port)
ret,addr = sk.recvfrom(1024)
print(ret)
print(addr)
sk.close()
UDPclient

udp的server不需要监听,也不需要建立连接

在启动服务之后,只能被动地等待客户端发过来的消息,

客户端发送消息的同时还会自带地址信息

消息回复的时候,不仅需要发送消息,还需要把对方地址填上

使用tcp,出现数据乱,不丢包

本质问题:不知道客户端发送数据包的大小

优化算法,连续发送多个send,小的数据包被合并

使用udp,出现丢包现象,因为udp是尽最大努力交付的协议

 hmac验证客户端的合法性

import hmac,os
import  socket
secret_key=b'egg'
def conn_auth(conn):
    print('开始验证新链接的合法性')
    msg=os.urandom(32)
    conn.sendall(msg)
    h=hmac.new(secret_key,msg)
    digest=h.digest()
    respone=conn.recv(len(digest))
    return hmac.compare_digest(respone,digest)
def server_socket():
    sk = socket.socket()
    sk.bind(('127.0.0.1',8080))
    sk.listen()
    while 1:
        conn,addr = sk.accept()
        res = conn_auth(conn)
        print(res)

server_socket()
server端
import  socket
import hmac
secret_key=b'egg'
def auth_conn(conn):
    msg=conn.recv(32)
    h=hmac.new(secret_key,msg)
    digest=h.digest()
    conn.sendall(digest)

def client():
    sk = socket.socket()
    sk.connect(('127.0.0.1',8080))
    auth_conn(sk)
    sk.close()
client()
client端

socketserver,在socket的基础上进行封装,可以实时同多个客户端通信

import socketserver
class Myserver(socketserver.BaseRequestHandler):
    def handle(self):
        self.data = self.request.recv(1024).strip()
        print("{} wrote:".format(self.client_address[0]))
        print(self.data)
        self.request.sendall(self.data.upper())

if __name__ == "__main__":
    HOST, PORT = "127.0.0.1", 9999
    # 设置allow_reuse_address允许服务器重用地址
    socketserver.TCPServer.allow_reuse_address = True
    # 创建一个server, 将服务地址绑定到127.0.0.1:9999
    server = socketserver.TCPServer((HOST, PORT),Myserver)
    # 让server永远运行下去,除非强制停止程序
    server.serve_forever()
server端
import socket

HOST, PORT = "127.0.0.1", 9999
data = "hello"

# 创建一个socket链接,SOCK_STREAM代表使用TCP协议
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
    sock.connect((HOST, PORT))          # 链接到客户端
    sock.sendall(bytes(data + "\n", "utf-8")) # 向服务端发送数据
    received = str(sock.recv(1024), "utf-8")# 从服务端接收数据

print("Sent:     {}".format(data))
print("Received: {}".format(received))
client

 

转载于:https://www.cnblogs.com/weidaijie/p/10322260.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值