socket

socket

 

TCP

 TCP

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

客户端
"""
cs = socket()               # 创建客户套接字
cs.connect()                # 尝试连接服务器
comm_loop:                  # 通讯循环
    cs.send()/cs.recv()     # 对话(发送/接收)
cs.close()                  # 关闭客户套接字
"""
伪代码
import socket

ip_port = ('127.0.0.1', 8001)
back_log = 5
buff_size = 1024

tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 创建socket
tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 重新使用IP和端口,解决OSError问题
tcp_server.bind(ip_port)  # 绑定服务器IP和端口
tcp_server.listen(back_log)  # 开始TCP监听, back_log表示最多同时监听5个


while True:
    conn, addr = tcp_server.accept()  # 被动接受TCP客户的连接,(阻塞式)等待连接的到来
    # print("conn:", conn)  # conn表示链接
    # print("addr:", addr)  # addr表示对方的地址

    while True:
        try:
            recv_msg = conn.recv(buff_size)  # 用链接接收TCP数据,表示最多收到的字节信息
            # if not recv_msg:break  # mac系统
            print("这是客户端发来的信息:", recv_msg.decode("utf-8"))
            conn.send("这里是服务端".encode("utf-8"))  # 发消息

        except ConnectionResetError:
            break

    # conn.close()  # 断开(关闭)链接

tcp_server.close()  # 关闭socket
tcp_sever_demo
import socket

ip_port = ('127.0.0.1', 8001)
buff_size = 1024

tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 创建socket
tcp_client.connect(ip_port)  # 链接服务端

while True:
    send_msg = input("发送内容:").strip()
    if not send_msg:
        continue
    tcp_client.send(send_msg.encode('utf-8'))  # 发送数据,数据都是以二进制形式进行传输的
    recv_msg = tcp_client.recv(buff_size)  # 接收数据
    print("这是服务端回复的信息:", recv_msg.decode("utf-8"))

tcp_client.close()  # 关闭socket
tcp_client_demo
1、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)


2、服务端套接字函数
s.bind()    绑定(主机,端口号)到套接字
s.listen()  开始TCP监听
s.accept()  被动接受TCP客户的连接,(阻塞式)等待连接的到来


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


4、公共用途的套接字函数
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()           关闭套接字


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


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

 

UDP

# server

ss = socket()   #创建一个服务器的套接字
ss.bind()       #绑定服务器套接字
inf_loop:       #服务器无限循环
    cs = ss.recvfrom()/ss.sendto() # 对话(接收与发送)
ss.close()  



# client

cs = socket()   # 创建客户套接字
comm_loop:      # 通讯循环
    cs.sendto()/cs.recvfrom()   # 对话(发送/接收)
cs.close()  
伪代码
import socket

ip_port = ("127.0.0.1", 8888)
buffer_size = 1024

udp_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # SOCK_DGRAM数据报
udp_server.bind(ip_port)


while True:
    # data = udp_server.recvfrom(buffer_size)
    # print(data)
    data, address = udp_server.recvfrom(buffer_size)
    print("udp客户端:", data.decode("utf-8"))

    data = "这里是udp服务端".encode("utf-8")
    udp_server.sendto(data, address)
udp_sever_demo
import socket

ip_port = ("127.0.0.1", 8888)
buffer_size = 1024

udp_client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # SOCK_DGRAM数据报

while True:
    data = input("请输入:").strip()
    if not data:
        continue

    send_data = data.encode("utf-8")
    udp_client.sendto(send_data, ip_port)
    data,address = udp_client.recvfrom(buffer_size)
    print("udp服务端:", data.decode("utf-8"))
udp_client_demo

 

解决粘包

import socket, subprocess, struct

ip_port = ('127.0.0.1', 8008)  # 主机地址
back_log = 5  # 最大监听数
buf_size = 1024  # 最多收到的1024字节
en_code = 'utf-8'  # 编码方式

tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 创建socket
tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 重新使用IP和端口,解决OSError问题
tcp_server.bind(ip_port)  # 设置应用的地址
tcp_server.listen(back_log)  # 设置最大监听数

while True:
    conn, addr = tcp_server.accept()

    while True:
        try:
            cmd = conn.recv(buf_size)  # 用链接接收TCP数据,表示最多收到的字节信息
            if not cmd:  # mac系统时强制切断客户端的处理方法
                break
            if cmd.decode(en_code) == "quit":  # quit时,退出
                break

            res = subprocess.Popen(cmd.decode(en_code),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stdin=subprocess.PIPE,
                                   stderr=subprocess.PIPE)

            err = res.stderr.read()
            out = res.stdout.read()
            if out:
                send_msg = out
            elif err:
                send_msg = err
            else:
                send_msg = "exec".encode("GBK")

            # 制作和传输数据有关的报头
            length = len(send_msg)
            data_length = struct.pack('i', length)
            conn.send(data_length)  # 发送报头

            # conn.send(send_msg)
            conn.sendall(send_msg)  # 传输全部数据

        except Exception as e:
            print(e)
            break

    conn.close()  # 断开(关闭)链接

tcp_server.close()  # 关闭socket
server
import socket, struct
from functools import partial

# 配置信息
address = ('127.0.0.1', 8008)
en_code = 'utf-8'
buf_size = 1024

tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_client.connect(address)

while True:
    send_msg = input('>>:').strip()
    if not send_msg:  # 发送内容为空
        continue

    if send_msg == 'quit':  # 发送内容为quit,退出
        tcp_client.send(send_msg.encode(en_code))
        break

    tcp_client.send(send_msg.encode(en_code))

    length_tuple = tcp_client.recv(4)  # 拿到和传输数据有关的报头
    data_length = struct.unpack('i', length_tuple)[0]

    # recv_msg = tcp_client.recv(buf_size)
    recv_msg = b''
    recv_size = 0
    while recv_size < data_length:
        recv_msg += tcp_client.recv(buf_size)
        recv_size += buf_size

    print(recv_msg.decode("GBK"))

tcp_client.close()
client

 

利用socketserver实现并发

import socketserver


class MyServer(socketserver.BaseRequestHandler):
    # 重写handle方法, 实现通讯循环
    def handle(self):
        print("conn is", self.request)
        print("addr is", self.client_address)

        while True:
            # 通讯循环
            # 收消息
            data = self.request.recv(1024)
            print("收到客户端的消息:", data)

            # 发消息
            self.request.sendall('收到了')



if __name__ == "__main__":
    s = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer)
    s.serve_forever()  # 连接循环
View Code

 

posted @ 2019-02-25 11:32  李小样  阅读(65)  评论(0编辑  收藏  举报