Socket

Posted litzhiai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Socket相关的知识,希望对你有一定的参考价值。

socket()模块函数用法

import socket
 socket.socket(socket_family,socket_type,protocal=0)
 socket_family 可以是 AF_UNIX(同主机) 或 AF_INET(网络,用这个)。socket_type 可以是 SOCK_STREAM(流式) 或 SOCK_DGRAM(报文)。protocol 一般不填,默认值为 0。
 
 获取tcp/ip套接字
 tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
 获取udp/ip套接字
 udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 
 由于 socket 模块中有太多的属性。我们在这里破例使用了from module import *语句。使用 from socket import *,我们就把 socket 模块里的所有属性都带到我们的命名空间里了,这样能 大幅减短我们的代码。
 例如tcpSock = socket(AF_INET, SOCK_STREAM)
服务端套接字函数
s.bind() 绑定(主机,端口号)到套接字
s.listen() 开始TCP监听
s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来

客户端套接字函数
s.connect() 主动初始化TCP服务器连接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

公共用途的套接字函数
s.recv() 接收TCP数据
s.send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
s.sendall() 发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
s.recvfrom() 接收UDP数据
s.sendto() 发送UDP数据
s.getpeername() 连接到当前套接字的远端的地址
s.getsockname() 当前套接字的地址
s.getsockopt() 返回指定套接字的参数
s.setsockopt() 设置指定套接字的参数
s.close() 关闭套接字

面向锁的套接字方法
s.setblocking() 设置套接字的阻塞与非阻塞模式
s.settimeout() 设置阻塞套接字操作的超时时间
s.gettimeout() 得到阻塞套接字操作的超时时间

面向文件的套接字的函数
s.fileno() 套接字的文件描述符
s.makefile() 创建一个与该套接字相关的文件

例1:TCP

技术分享图片
from socket import *
phone=socket(AF_INET,SOCK_STREAM)  #TCP连接
phone.bind((127.0.0.1,8081))
phone.listen(5) #最多5个监听

conn,addr=phone.accept() #等待连接进入
while True:
    data=conn.recv(1024)
    print(server===>)
    print(data)
    conn.send(data.upper())
conn.close()
phone.close()
服务端
技术分享图片
from socket import *

phone=socket(AF_INET,SOCK_STREAM)
phone.connect((127.0.0.1,8081))

while True:
    msg=input(>>: ).strip()
    phone.send(msg.encode(utf-8))
    print(client====>)
    data=phone.recv(1024)
    print(data)
客户端

 

例2:UDP

技术分享图片
from socket import *
phone=socket(AF_INET,SOCK_DGRAM)
phone.bind((127.0.0.1,8082))
while True:
    msg,addr=phone.recvfrom(1024)
    phone.sendto(msg.upper(),addr)
服务端
技术分享图片
from socket import *
phone=socket(AF_INET,SOCK_DGRAM)
while True:
    msg=input(>>: )
    phone.sendto(msg.encode(utf-8),(127.0.0.1,8082))
    msg,addr=phone.recvfrom(1024)
    print(msg)
客户端

 

tcp服务端:

ss = socket() #创建服务器套接字
ss.bind()      #把地址绑定到套接字
ss.listen()      #监听链接
inf_loop:      #服务器无限循环
    cs = ss.accept() #接受客户端链接
    comm_loop:         #通讯循环
        cs.recv()/cs.send() #对话(接收与发送)
    cs.close()    #关闭客户端套接字
ss.close()        #关闭服务器套接字(可选)

 

tcp客户端:

1 cs = socket()    # 创建客户套接字
2 cs.connect()    # 尝试连接服务器
3 comm_loop:        # 通讯循环
4     cs.send()/cs.recv()    # 对话(发送/接收)
5 cs.close()            # 关闭客户套接字

 

案例:

技术分享图片
import socket
ip_port=(127.0.0.1,8081)
BUFSIZE=1024
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # TCP 连接
s.bind(ip_port) #
s.listen(5)     #可以5个等待连接


while True:                         #新增接收链接循环,可以不停的接收
    conn,addr=s.accept()            #等待连接
    print(conn)
    print(addr)
    while True:                         #新增通信循环,可以不断的通信,收发消息
        msg=conn.recv(BUFSIZE)             #听消息,听话

        if len(msg) == 0:break        #如果不加,那么正在链接的客户端突然断开,recv便不再阻塞,死循环发生

        print(msg,type(msg))

        conn.send(msg.upper())          #发消息,说话

    conn.close()                    #挂电话

s.close()                       #手机关机
服务端
技术分享图片
import socket
ip_port=(127.0.0.1,8081)
BUFSIZE=1024
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

s.connect_ex(ip_port)           #拨电话

while True:                             #新增通信循环,客户端可以不断发收消息
    msg=input(>>: ).strip()
    if len(msg) == 0:continue
    s.send(msg.encode(utf-8))         #发消息,说话(只能发送字节类型)

    feedback=s.recv(BUFSIZE)                           #收消息,听话
    print(feedback.decode(utf-8))

s.close()                                       #挂电话
客户端

 

重用socket接口

重用socket接口,closesocket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket:

#加入一条socket配置,重用ip和端口

phone=socket(AF_INET,SOCK_STREAM)
phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
phone.bind((127.0.0.1,8080))

 

linux解决大量TIME_WAIT的方法:

发现系统存在大量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 时间

 





























以上是关于Socket的主要内容,如果未能解决你的问题,请参考以下文章

Python干货socket中的listen()参数(数字)到底代表什么?

paper 78:sniff抓包程序片段

通过 c# 与 socket.io 服务器通信

微信小程序代码片段

VSCode自定义代码片段——CSS选择器

谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js