进军的socket

在学socket有时候我们会遇到这种问题:

解决方法一:

在服务端中加入:severTCP.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

#!/urs/bin/evn python
# -*- coding:utf-8 -*-
import socket
severTCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
severTCP.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
severTCP.bind(("127.0.0.1", 8888))  # 绑定端口
severTCP.listen(5)           # 监听
print("starting....")
client, address = severTCP.accept()  # 等待连接
while True:  # 通信循环
    data = client.recv(1024)  # 单位:byte. 1024代表最大接收1024个byte,收数据
    print("来%s客服端的数据" % client, data.decode("utf-8"))
    client.send(data.upper())  # 发数据
client.close()
severTCP.close()

方法二:

发现系统存在大量TIME_WAIT状态的连接,通过调整linux内核参数解决,
vi /etc/sysctl.conf

编辑文件,加入以下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
 
然后执行 /sbin/sysctl -p 让参数生效。
 
net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;

net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;

net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。

net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间
View Code
客户端发送空,卡住,主要是在原因:缓冲区为空,recv就卡住:

服务端:

 

#!/urs/bin/evn python
# -*- coding:utf-8 -*-
import socket
clientTCP = socket.socket(socket.AF_INET,
                          socket.SOCK_STREAM)
clientTCP.connect(("127.0.0.1", 8888))
while True:
    msg = input(">>:").strip()
    if not msg:continue
    # if len(msg)==0:continue
    clientTCP.send(msg.encode("utf-8"))
    data = clientTCP.recv(1024)
    print(data.decode("utf-8"))
clientTCP.close()

 

 

 结果:

客户端

服务端:

 

 当客户端异常断开连接,看见服务端:

Liunx :

#!/urs/bin/evn python
# -*- coding:utf-8 -*-
import socket
severTCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
severTCP.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
severTCP.bind(("127.0.0.1", 8888))  # 绑定端口
severTCP.listen(5)           # 监听
print("starting....")
client, address = severTCP.accept()  # 等待连接
while True:  # 通信循环
    data = client.recv(1024)  # 单位:byte. 1024代表最大接收1024个byte,收数据
    if not data: break   # 针对Liunx
    # if len(data): break
    print("来%s客服端的数据" % client, data.decode("utf-8"))
    client.send(data.upper())  # 发数据
client.close()
severTCP.close()
View Code

windows:

#!/urs/bin/evn python
# -*- coding:utf-8 -*-
import socket
severTCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
severTCP.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
severTCP.bind(("127.0.0.1", 8888))  # 绑定端口
severTCP.listen(5)           # 监听
print("starting....")
client, address = severTCP.accept()  # 等待连接
while True:  # 通信循环
    try:
        data = client.recv(1024)  # 单位:byte. 1024代表最大接收1024个byte,收数据
        print("来%s客服端的数据" % client, data.decode("utf-8"))
        client.send(data.upper())  # 发数据
    except ConnectionResetError:
        break
client.close()
severTCP.close()

结果:

客户端

 

 服务端:

 

 实现服务端对多个客户端服务(但这没有并发结果)

#!/urs/bin/evn python
# -*- coding:utf-8 -*-
import socket
severTCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
severTCP.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
severTCP.bind(("127.0.0.1", 8888))  # 绑定端口
severTCP.listen(5)           # 监听
print("starting....")
while True:
    client, address = severTCP.accept()  # 等待连接
    while True:  # 通信循环
        try:
            data = client.recv(1024)  # 单位:byte. 1024代表最大接收1024个byte,收数据
            if not data:break  # Liunx
            print("来%s客服端的数据" % client, data.decode("utf-8"))
            client.send(data.upper())  # 发数据
        except ConnectionResetError:
            break
    client.close()
severTCP.close()
View Code

 

 一个简单聊天功能:

服务端:

#!/urs/bin/env python
# -*- coding:utf-8 -*-
import socket

sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock_server.bind(("127.0.0.1", 8888))
sock_server.listen(1)  # 开始监听,1代表在允许有一个连接排队,更多的新连接连进来时就会被拒绝
while True:
    conn, addr = sock_server.accept()  # 阻塞直到有连接为止,有了一个新连接进来后,就会为这个请求生成一个连接对象
   print("新人来了", conn.getpeername())

   with conn:
print('Connected by', addr) while True: try: data = conn.recv(1024) # 接收1024个字节 print("recv from zq:", conn.getpeername(), data.decode()) if not data: break # 收不到数据,就break response = input(">>>").strip() conn.send(response.encode("utf-8")) #print("send to xqx:", response) except ConnectionResetError: break conn.close() sock_server.close()

客户端:

#!/urs/bin/evn python
# -*- coding:utf-8 -*-
import socket
clientTCP = socket.socket(socket.AF_INET,
                          socket.SOCK_STREAM)
clientTCP.connect(("127.0.0.1", 8888))
while True:
    msg = input(">>:").strip()
    if not msg:continue
    # if len(msg)==0:continue
    clientTCP.send(msg.encode("utf-8"))
    data = clientTCP.recv(1024)
    print('xqx',data.decode("utf-8"))
clientTCP.close()

结果:

客户端

服务端

 

文件传输:

#! /urs/bin/evn python
# -*- coding:utf-8 -*-
import socket
import struct
import json
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # tcp协议
# 链接服务端
phone.connect(("127.0.0.1", 8083))
# 发,收消息
while True:
    # 1 发命令
    cmd = input(">>>:").strip()
    if not cmd:continue
    phone.send(cmd.encode("utf-8"))  #
    # 2 以写的方式打开一个新文件,接收服务端发来的文件的内容写入客户端
    # 第一步:先收报头长度
    obj = phone.recv(4)
    header_size = struct.unpack("i", obj)[0]
    # 第二步:再收报头
    header_bytes = phone.recv(header_size)
    # 第三步:从报头中解析出对真实数据的描述信息(数据的长度)
    header_json = header_bytes.decode("utf-8")
    heade_dic = json.loads(header_json)
    print(heade_dic)
    total_size = heade_dic["file_size"]
    # 第四步:接收真实数据

    filename = heade_dic["filename"]
    with open(filename, "wb") as f:
        recv_size = 0
        while recv_size < total_size:
            line = phone.recv(1024)  # 收。接命令
            f.write(line)
            recv_size += len(line)

# 关闭
phone.close()
View Code
#! /urs/bin/evn python
# -*- coding:utf-8 -*-
import socket
import struct
import json
import os
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # tcp协议
phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定ip和端口
phone.bind(("127.0.0.1", 8083))
# 监听
phone.listen(5)
print("statting....")
# 等待链接
while True:  # 链接循环。这里暂时没有并发功能
    conn, client_add = phone.accept()
    # 这一步对应客服端connect
    print(client_add)
    while True:  # 通信循环
        try:
            # 1 收命令
            res = conn.recv(8192)
            # 单位:byte. 1024代表最大接收1024个byte
            if not res: break
            # 针对异常后(liunx客服端强行停机后,服务端进入死循环,只适用Linux)
            # print("客服端的数据", cmd)
            # 2 解析命令。提取相应命令参数
            cmds = res.decode("utf-8").split()
            filename = cmds[1]

            #  以读的方式打开文件。读取文件内容发送给客服端

            # 第一步:制作固定长度的报头
            heade_dic = {
                "filename": filename,
                "md5": "xxxx",
                "file_size": os.path.getsize(filename)
            }
            heade_json = json.dumps(heade_dic)
            header_bytes = heade_json.encode("utf-8")
            # 第二步:先发送报头的长度
            conn.send(struct.pack("i", len(header_bytes)))
            # 第三步:再发报头
            # print(len(stdout) + len(stderr))
            conn.send(header_bytes)
            # conn.send(str(total_size).encode("utf-8"))
            # 第四步:再发真实的数据
            with open(filename, "rb") as f:
                for line in f:
                    conn.send(line)
        except ConnectionResetError:
            # 适用window操作系统
            break
    conn.close()
phone.close()
View Code

转载于:https://www.cnblogs.com/zqxqx/p/9345457.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值