zoukankan      html  css  js  c++  java
  • Python学习日记(三十) Socket模块使用

    Socket(套接字)

    套接字是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。

    发展:套接字最初是由加利福尼亚大学Berkely分校为Unix系统开发的网络通信接口。后来随着TCP/IP网络的发展,套接字成为最为通用的应用程序接口,也是在Internet上进行应用开发最为通用的API.

    应用:

    实现:

    基于TCP协议实现Sever端和Client端的信息互通

    Sever端:

    import socket
    sk = socket.socket()            #创建服务器的套接字
    sk.bind(('127.0.0.1',8080))     #把地址绑定到套接字
    
    sk.listen()                     #监听链接
    conn,addr = sk.accept()         #接收到客户端的连接和地址
    ret = conn.recv(1024)           #接收客户端信息
    print(ret)                      #打印客户端的信息
    
    conn.send(b'hi')                #向客户端发送信息
    conn.close()                    #关闭客户端的连接
    sk.close()                      #关闭服务器套接字

    Client端:

    import socket
    sk = socket.socket()             #创建客户端的套接字
    sk.connect(('127.0.0.1',8080))   #尝试连接服务器
    
    sk.send(b'hello')                #向服务器发送消息
    ret = sk.recv(1024)              #接收服务器发送的消息
    print(ret)                       #打印服务器发送的消息
    
    sk.close()                       #关闭客户端的套接字

    Sever端和Client端两边都要对应接收和发送信息,不能只接不收或只收不接且执行时要先执行Sever端再去执行Client端,执行结果:

    当重启服务器时遇到地址已被使用的问题

    解决方案:

    如何让客户端和服务器能够多次进行对话?

    Sever端:

    import socket
    from socket import SOL_SOCKET,SO_REUSEADDR
    sk = socket.socket()              #创建服务器的套接字
    sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    sk.bind(('127.0.0.1',8080))       #把地址绑定到套接字
    sk.listen()                       #监听链接
    conn,addr = sk.accept()           #接收到客户端的连接和地址
    
    print(addr)                       #打印客户端的地址
    ret = conn.recv(1024)             #接收客户端信息
    print(ret)                        #打印客户端的信息
    conn.send(b'hi')                  #向客户端发送信息
    print(addr)                       #打印客户端的地址
    ret = conn.recv(1024)             #接收客户端信息
    print(ret)                        #打印客户端的信息
    conn.send(b'hi')                  #向客户端发送信息
    
    conn.close()                      #关闭客户端的连接
    sk.close()                        #关闭服务器套接字

    Client端:

    import socket
    sk = socket.socket()                #创建客户端的套接字
    sk.connect(('127.0.0.1',8080))      #尝试连接服务器
    
    sk.send(b'hello')                   #向服务器发送消息
    ret = sk.recv(1024)                 #接收服务器发送的消息
    print(ret)                          #打印服务器发送的消息
    sk.send(b'hello')                   #向服务器发送消息
    ret = sk.recv(1024)                 #接收服务器发送的消息
    print(ret)                          #打印服务器发送的消息
    
    sk.close()                          #关闭客户端的套接字

    执行结果:

    因此我们只要在Sever端获取到Client端后让它去循环接收和发送消息、让Client端在连接上Sever端后去循环发送和接收消息就能完成一个一直发送接收消息的过程,但这个过程是一个死循环,我们需要加上一些条件让它更加完善

    Sever端:

    import socket
    import time
    from json import dumps
    from socket import SOL_SOCKET,SO_REUSEADDR
    sk = socket.socket()                                                                    #创建服务器的套接字
    sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    sk.bind(('127.0.0.1',8080))                                                             #把地址绑定到套接字
    sk.listen()                                                                             #监听链接
    conn,addr = sk.accept()                                                                 #接收到客户端的连接和地址
    
    while 1:
        ret = conn.recv(1024).decode('utf-8')                                               #接收客户端信息
        if ret.strip() == 'bye' or ret.strip() == 'bye'.capitalize():                       #跳出循环的条件
            conn.send(b'bye')                                                               #发送bytes类型的Bye
            print('Client has disconnected!')
            break
        print(time.asctime(time.localtime(time.time())) + ' ' +  dumps(addr) + ':' + ret)   #格式化打印客户端发来的消息
        sendInfo = input(time.asctime(time.localtime(time.time())) + ' <<<')
        conn.send(sendInfo.encode('utf-8'))                                                 #向客户端发送信息
    
    conn.close()                                                                            #关闭客户端的连接
    sk.close()                                                                              #关闭服务器套接字

    Client端:

    import socket
    import time
    sk = socket.socket()                                                                #创建客户端的套接字
    sk.connect(('127.0.0.1',8080))                                                      #尝试连接服务器
    
    while 1:
        sendInfo = input(time.asctime(time.localtime(time.time())) + ' <<<')
        sk.send(sendInfo.encode('utf-8'))                                               #向服务器发送消息
        ret = sk.recv(1024).decode('utf-8')                                             #接收服务器发送的消息
        if ret.strip() == 'bye' or ret.strip() == 'bye'.capitalize():                   #跳出循环的条件
            sk.send(b'bye')                                                             #发送bytes类型的Bye
            print('Sever has disconnected!')
            break
        print(time.asctime(time.localtime(time.time())) + ' ["127.0.0.1", 8080]:' + ret)#格式化打印服务器发来的消息
    
    sk.close()                                                                          #关闭客户端的套接字

    执行结果:

    基于UDP协议实现Sever端和Client端的信息互通

    实现简单传递信息

    Sever端:

    import socket
    sk = socket.socket(type=socket.SOCK_DGRAM)      #创建服务器套接字
    sk.bind(('127.0.0.1',8080))                     #绑定服务器套接字
    
    msg,addr = sk.recvfrom(1024)                    #接收到客户端的信息和地址
    print(msg.decode('utf-8'))                      #将客户端传递来的信息解码并打印出来
    sk.sendto(b'Hello client!',addr)                #将bytes类型的信息发送到客户端的地址
    
    sk.close()                                      #关闭服务器套接字

    Client端:

    import socket
    sk = socket.socket(type=socket.SOCK_DGRAM)      #创建客户端套接字
    ip_port = ('127.0.0.1',8080)
    
    sk.sendto(b'Hello sever!',ip_port)              #客户端发送信息
    ret,addr = sk.recvfrom(1024)                    #接收到服务器的地址和信息
    print(ret.decode('utf-8'))                      #打印收到的信息
    
    sk.close()                                      #关闭客户端套接字

    执行结果:

    多人版:

    Sever端:

    import socket
    sk = socket.socket(type=socket.SOCK_DGRAM)                  #创建服务器套接字
    sk.bind(('127.0.0.1',8080))                                 #绑定服务器套接字
    
    while 1:
        msg,addr = sk.recvfrom(1024)                            #接收到客户端的信息和地址
        str_msg = msg.decode('utf-8')
        print(addr,str_msg)
        info = input('<<<').encode('utf-8')
        sk.sendto(info,addr)
    
    sk.close()                                                  #关闭服务器套接字

    Client1:

    import socket
    sk = socket.socket(type=socket.SOCK_DGRAM)                              #创建客户端套接字
    ip_port = ('127.0.0.1',8080)
    
    while 1:
        info = input('Client1:')
        info = ('33[32m来自Client1的消息:%s33[0m'%info).encode('utf-8')
        sk.sendto(info,ip_port)
        msg,addr = sk.recvfrom(1024)
        str_msg = msg.decode('utf-8')
        print(str_msg)
    
    
    sk.close()                                                              #关闭客户端套接字

    Client2:

    import socket
    sk = socket.socket(type=socket.SOCK_DGRAM)                              #创建客户端套接字
    ip_port = ('127.0.0.1',8080)
    
    while 1:
        info = input('Client2:')
        info = ('33[36m来自Client2的消息:%s33[0m' % info).encode('utf-8')
        sk.sendto(info, ip_port)
        msg, addr = sk.recvfrom(1024)
        str_msg = msg.decode('utf-8')
        print(str_msg)
    
    sk.close()                                                              #关闭客户端套接字

    执行结果:

     

     

     

    udp的Sever不需要进行监听也不需要建立连接,在启动服务之后只能被动得等待客户端发送消息来,客户端发送消息的同时还会自带地址信息,消息回复的时候不仅要发送消息还要把对方的地址给填上

  • 相关阅读:
    java算法
    2012 要找回曾经的忘我的激情
    啊啊啊
    利用ORACLE JOB 模拟多线程应用
    有没有一种数据库叫思科
    且行好事,莫问前程
    女人浪漫的好点子
    What is the difference between interface and abstract class
    优秀是一种习惯
    C#判断ContextMenuStrip右键菜单的来源(从哪个控件弹出来的) (转载)
  • 原文地址:https://www.cnblogs.com/Fantac/p/11521009.html
Copyright © 2011-2022 走看看