zoukankan      html  css  js  c++  java
  • 网络编程

    推荐链接:‘网络编程’ http://www.cnblogs.com/Eva-J/articles/8244551.html#_label2
    服务端一直是监听状态的。
    客户端单工通信请求连接服务端,服务端通过然后请求客户端建立连接,单工。客户端接收到通过并回复。然后建立起双工通信。合并了2,3条信息

    有收必有发,收发必相等。
    断开可以是客户端也可以是服务端先。
    建立连接后,后面的发送是基于连接下发送消息。即使没有连接,服务端和客户端也可以互发消息的。

    import socket
    sk = socket.socket()
    sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字
    sk.listen() #监听连接,个数
    conn,addr = sk.accept() #接受客户端连接,阻塞
    ret = conn.recv(1024) #接收客户端信息
    print(ret) #打印客户端信息
    conn.send(b'hi') #向客户端发送信息
    conn.close() #关闭客户端套接字
    sk.close() #关闭服务器套接字(可选)

    创建对象,
    绑定ip端口
    监听

    accept和connect实现了三次握手的过程

    conn.close()和sk.accept().close区别:
    conn.close()为了断开单个连接的客户端
    sk.accept().close服务端断开,所有客户端都连接不上了

    bind ip 端口 ip为127的只能自己访问,IP为自己的ip可以提供给他人访问

    sk.send("".encode())这里编码是啥,服务端ret = conn.recv(1024)就要解码 ret.decode
    sk.send(b""),服务端ret = conn.recv(1024)
    收发对应上

    input实现聊天。
    发送消息为input信息
    服务端conn.send(b'hi') ret = conn.recv(1024)

    为了实现多次聊天
    将input消息发送消息,接收打印消息放入死循环 关闭和accept都不能在死循环里。

    为了实现退出聊天,加个对输入消息的判断,退出死循环:
    客户端发送退出,服务端接收到的就退出,
    服务端发送退出,服务端退出循环就直接关闭连接然后关闭sk,客户端报错
    外层再加个while循环,内层循环在conn,addr = sk.accept(),conn.close() 直接,这样关闭一个连接,那么可以进行下一个连接:

    ret=sk.send(input(">>>").encode("utf-8"))如果有变量接收,那么自动打印ret字节长度

    input在这里只能实现一来一回

    多人能同时聊天,同时互连,发消息给谁-服务端进行转发
    sk.listen(n)允许多少个人等待
    -----udp
    服务端recvfrom这样知道是谁发的,
    客户端recv就可以,因为已经知道是发给谁,只要内容就可以了

    tcp不能1对多因为占线了,双层循环
    udp实现了服务端1对多(聊天)(加上识别身份)

    --------udp创建
    udp服务端:
    import socket
    udp_sk = socket.socket(type=socket.SOCK_DGRAM) #创建一个服务器的套接字
    udp_sk.bind(('127.0.0.1',9000)) #绑定服务器套接字
    while True:
    msg,addr = udp_sk.recvfrom(1024)
    if msg.decode("utf-8").upper()=="Q":break
    print(msg.decode())
    a=input(">>>").encode("utf-8")
    udp_sk.sendto(a,addr) # 对话(接收与发送)
    if a.decode().strip(">>>").upper() == "Q": break
    udp_sk.close()

    udp客户端:
    import socket
    udp_sk = socket.socket(type=socket.SOCK_DGRAM) #创建一个服务器的套接字
    udp_sk.bind(('127.0.0.1',9000)) #绑定服务器套接字
    while True:
    msg,addr = udp_sk.recvfrom(1024)
    if msg.decode("utf-8").upper()=="Q":break
    print(msg.decode())
    a=input(">>>").encode("utf-8")
    udp_sk.sendto(a,addr) # 对话(接收与发送)
    if a.decode().strip(">>>").upper() == "Q": break
    udp_sk.close()

    udp服务端:
    创建一个udp对象加参数type=socket.SOCK_DGRAM,
    对象.bind绑定ip端口
    接收信息 对象.recvfrom(字节数)
    发送信息 对象.sendto(字节类型数据)
    关闭对象 对象.close

    udp客户端:
    创建一个udp对象加参数socket.socket(type=socket.SOCK_DGRAM)
    发送给谁:对象.sendto(字节内容,ip端口元组)
    接收信息:对象.recv(字节数)
    不需要关闭,udp对象没有关闭方法。

    1)二者接收到的内容显示一下
    2)想不断接收发送那就将接收数据发送数据放到while循环
    3)想停止客户端while循环那就判断发送的指定字符为Q退出循环
    4)客户端退出while循环停止服务端跟随停那么服务端判断接收到指定字符Q,break循环
    5)服务端突然停

    6)想退出while循环可以写成一行:if a.decode().strip(">>>").upper()=="Q":break
    7)服务端未开或服务端突然停止,客户端发送数据报错:[WinError 10054] 远程主机强迫关闭了一个现有的连接。
    8)服务端突然停止,客户端在等待服务端回复,似乎客户端会卡住,不退出,输入内容因为不是在发送阶段所以没反应
    9)如果想服务端和客户端有个想要退出Q,那么都是在自己这里发送之后判断发送是否为Q,在对方接收后面打印接收之前就可以判断是否为Q,是则breck循环。一般两方都停的适用于tcp的连接。
    10)如果想给每个和服务端通话的客户端加个标签,那么只需要将客户端发送的数据加个标签
    11)udp没有服务端没有listen监听端口,它可以服务端1对多通信。给每个客户端加个name,将name发送出去以识别是谁
    12)客户端 sendto忘记加IP端口元组,报错:sendto() takes 2 or 3 arguments (1 given)
    13)服务端sendto(字节内容,ip端口元组),[1]客户端 对象.recvfrom(1024)接收到的是个元组(字节内容,ip端口元组)[2]客户端 对象.recv(1024)接收到的是字节内容,比如:b'2'

    报错:
    1)
    2)
    3)udp服务端,udp客户端,将客户端的(type=socket.SOCK_DGRAM)改为()报错:
    OSError: [WinError 10057] 由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。

    sendto的问题:
    正确1:服务端udp_sk.sendto(a,addr) 客户端: back_msg,addr=udp_sk.recvfrom(1024)
    正确2:服务端:udp_sk.sendto(a,addr) 客户端:back_msg=udp_sk.recv(1024)
    1)服务端: udp_sk.send(a,addr) 客户端 back_msg,addr=udp_sk.recvfrom(1024)
    报错:TypeError: an integer is required (got type tuple)
    2)服务端:udp_sk.send(a) 客户端 back_msg,addr=udp_sk.recvfrom(1024)
    报错:OSError: [WinError 10057] 由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。
    3)服务端:udp_sk.sendto(a) 客户端:back_msg,addr=udp_sk.recvfrom(1024)
    报错:TypeError: sendto() takes 2 or 3 arguments (1 given)
    4)服务端:udp_sk.sendto(a,addr) 客户端:back_msg,addr=udp_sk.recv(1024)
    客户端报错:ValueError: not enough values to unpack (expected 2, got 1)

    综上:udp用sendto,发送内容和IP端口组成的元组,接收用recvfrom则接收两个内容,用recv只是接收发送的数据。


    TCP

    tcp连接:

    import socket
    sk = socket.socket()
    sk.bind(('127.0.0.1',9000))  #把地址绑定到套接字
    sk.listen()          #监听链接
    conn,addr = sk.accept() #接受客户端链接
    ret = conn.recv(1024)  #接收客户端信息
    print(ret)       #打印客户端信息
    conn.send(b'hi')        #向客户端发送信息
    conn.close()       #关闭客户端套接字
    sk.close()        #关闭服务器套接字(可选)
    -----结果:
    b'hello!'
    
    import socket
    sk = socket.socket()           # 创建客户套接字
    sk.connect(('127.0.0.1',9000))    # 尝试连接服务器
    sk.send(b'hello!')
    ret = sk.recv(1024)         # 对话(发送/接收)
    print(ret)
    sk.close()            # 关闭客户套接字
    ------------结果:
    b'hi'
    

    tcp连接实现一直通话

    import socket
    sk = socket.socket()
    sk.bind(('127.0.0.1',9000))  #把地址绑定到套接字
    sk.listen()          #监听链接
    conn, addr = sk.accept()  # 接受客户端链接。产生一个阻塞。时
    while True:
        ret = conn.recv(1024).decode("utf-8")  #接收客户端信息
        print(ret)       #打印客户端信息
        msg=input(">>>")
        conn.send(msg.encode("utf-8"))        #向客户端发送信息
    conn.close()       #关闭客户端套接字
    sk.close()        #关闭服务器套接字(可选)
    ----------结果:
    c1
    >>>s1
    c2
    >>>
    
    import socket
    sk = socket.socket()           # 创建客户套接字
    sk.connect(('127.0.0.1',9000))    # 尝试连接服务器
    while True:
        msg=input(">>>")
        sk.send(msg.encode("utf-8"))
        ret = sk.recv(1024).decode("utf-8")         # 对话(发送/接收)
        print(ret)
    sk.close()            # 关闭客户套接字
    ---------结果:
    >>>c1
    s1
    >>>c2
    

    tcp退出一直聊天

    import socket
    sk = socket.socket()
    sk.bind(('127.0.0.1',9000))  #把地址绑定到套接字
    sk.listen()          #监听链接
    conn, addr = sk.accept()  # 接受客户端链接
    while True:
        ret = conn.recv(1024).decode("utf-8")  #接收客户端信息
        if ret.upper()=="Q":break
        print(ret)       #打印客户端信息
        msg=input(">>>")
        conn.send(msg.encode("utf-8"))        #向客户端发送信息
        if msg.upper()=="Q":break
    conn.close()       #关闭客户端套接字
    sk.close()        #关闭服务器套接字(可选)
    ------------结果:
    c1
    >>>c2
    Process finished with exit code 0
    
    import socket
    sk = socket.socket()           # 创建客户套接字
    sk.connect(('127.0.0.1',9000))    # 尝试连接服务器
    while True:
        msg=input(">>>")
        sk.send(msg.encode("utf-8"))
        if msg.upper()=="Q":break
        ret = sk.recv(1024).decode("utf-8")         # 对话(发送/接收)
        if ret.upper()=="Q":break
        print(ret)
    sk.close()            # 关闭客户套接字
    ----------------结果:
    >>>c1
    c2
    >>>q
    Process finished with exit code 0
    

    tcp连接,退出一个连接后可以进入下一个连接:

    import socket
    sk = socket.socket()
    sk.bind(('127.0.0.1',9000))  #把地址绑定到套接字
    sk.listen()          #监听连接,允许等待的个数
    while True:
        conn, addr = sk.accept()  # 接受客户端连接
        while True:
            ret = conn.recv(1024).decode("utf-8")  #接收客户端信息
            if ret.upper()=="Q":break
            print(ret)       #打印客户端信息
            msg=input(">>>")
            conn.send(msg.encode("utf-8"))        #向客户端发送信息
            if msg.upper()=="Q":break
        conn.close()       #关闭客户端套接字
    sk.close()        #关闭服务器套接字(可选)
    
    
    import socket
    sk = socket.socket()           # 创建客户套接字
    sk.connect(('127.0.0.1',9000))    # 尝试连接服务器
    while True:
        msg=input(">>>")
        sk.send(msg.encode("utf-8"))
        if msg.upper()=="Q":break
        ret = sk.recv(1024).decode("utf-8")         # 对话(发送/接收)
        if ret.upper()=="Q":break
        print(ret)
    sk.close()            # 关闭客户套接字
    

    tcp连接不同的用户不同的名字识别:

    import socket
    sk = socket.socket()
    sk.bind(('127.0.0.1',9000))  #把地址绑定到套接字
    sk.listen()          #监听连接,允许等待的个数
    while True:
        conn, addr = sk.accept()  # 接受客户端连接
        while True:
            ret = conn.recv(1024).decode("utf-8")  #接收客户端信息
            if ret.upper()=="Q":break
            print(ret)       #打印客户端信息
            msg=input(">>>")
            conn.send(msg.encode("utf-8"))        #向客户端发送信息
            if msg.upper()=="Q":break
        conn.close()       #关闭客户端套接字
    sk.close()        #关闭服务器套接字(可选)
    --------结果:
    小马过河1234QQ:xiao
    >>>q
    小郭吹雪1234QQ:ming
    >>>
    
    import socket
    sk = socket.socket()           # 创建客户套接字
    sk.connect(('127.0.0.1',9000))    # 尝试连接服务器
    name_and_qq="小郭吹雪1234QQ"
    while True:
        msg=input(">>>")
        sk.send((name_and_qq+":"+msg).encode("utf-8"))
        if msg.upper()=="Q":break
        ret = sk.recv(1024).decode("utf-8")         # 对话(发送/接收)
        if ret.upper()=="Q":break
        print(ret)
    sk.close()            # 关闭客户套接字
    

    1.基于tcp协议实现聊天基础需求:

    # 1.server和client端连接之后,能知道对面这个人是哪一个好友  qq号
    # 2.不同好友的聊天颜色不同 https://www.cnblogs.com/Eva-J/p/8330517.html
    
    import random
    import socket
    sk = socket.socket()
    sk.bind(('127.0.0.1',9000))  #把地址绑定到套接字
    sk.listen()          #监听连接,允许等待的个数
    while True:
        color=random.randint(30,37)
        color="33[amb33[0m".replace("a",str(color))
        conn, addr = sk.accept()  # 接受客户端连接
        while True:
            ret = conn.recv(1024).decode("utf-8")  #接收客户端信息
            if ret.upper()=="Q":break
            print(color.replace("b",ret))       #打印客户端信息
            msg=input(">>>")
            conn.send(msg.encode("utf-8"))        #向客户端发送信息
            if msg.upper()=="Q":break
        conn.close()       #关闭客户端套接字
    sk.close()        #关闭服务器套接字(可选)
    
    # ----------结果:
    # 小马过河1234QQ:xiao
    # >>>q
    # 小郭吹雪1234QQ:ximgn
    # >>>
    
    import socket
    sk = socket.socket()           # 创建客户套接字
    sk.connect(('127.0.0.1',9000))    # 尝试连接服务器
    name_and_qq="小马过河1234QQ"
    while True:
        msg=input(">>>")
        sk.send((name_and_qq+":"+msg).encode("utf-8"))
        if msg.upper()=="Q":break
        ret = sk.recv(1024).decode("utf-8")         # 对话(发送/接收)
        if ret.upper()=="Q":break
        print(ret)
    sk.close()            # 关闭客户套接字
    
  • 相关阅读:
    Charles手机端抓包--证书
    新浪微盘批量下载
    [3140] Sublime Text 2.x, 3.x 通用注册码、密钥集合
    栈的数组实现
    栈的链表实现
    基数排序
    多项式相乘-数组实现
    最大子序列和问题的四种算法
    链表的实现
    时间同步算法与Simple Ring-based election algorithm算法分析-转载
  • 原文地址:https://www.cnblogs.com/machangwei-8/p/10826489.html
Copyright © 2011-2022 走看看