Python网络编程-----TCP

1.TCP

TCP通信模型中,在通信开始之前,⼀定要先建⽴相关的连接,才能发送数据,类似于⽣活中,"打电话"。TCP编程分为客户端和服务器端两部分组成,所以我们需要首先完成服务器端的编程,之后完成客户端的编程,再使用客户端连接服务器端。

TCP是有状态的,安全的,可靠的,有连接的协议。TCP建立连接时,要经过三次握手,连接断开时要经过四次挥手。在未连接时,服务器等待客户端的连接,当客户端连接上时,向客户端发送输入的信息。

2.TCP服务器的搭建流程

(1)、socket创建⼀个套接字; (2)、bind绑定ip和port;(3)、listen使套接字变为可以被动链接;(4)、accept等待客户端的链接;(5)、recv/send接收发送数据。 

import socket
import time
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server.bind(("", 8080))
# 表示监听的数量 在Linux下是无效的
server.listen(10)
print("服务器开始监听了……")
# 等待客户端的连接 返回的是一个元组包含客户端对象和它的套接字 这个客户端对象用于向客户端发送信息
# 其中laddr ===>local address  raddr ===>remote address
data = server.accept()
server.send()
# print(data)
time.sleep(10)
# 关闭服务器
server.close()

用网络调试助手连接后返回如下结果

服务器开始监听了……
(<socket.socket fd=440, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.14.30', 8080), raddr=('192.168.14.30', 51853)>, ('192.168.14.30', 51853))

3.服务器端发送数据和接受数据

服务器端

import socket
import time
# 获取一个基于TCP协议的socket对象
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server.bind(("", 8080))
# 表示监听的数量 在Linux下是无效的
server.listen(10)
print("服务器开始监听了……")
client_socket, client_address = server.accept()
client_socket.send("本服务器来自于阎王殿,告诉你一个不幸的消息,你命不久矣".encode("utf-8"))
msg = client_socket.recv(1024).decode("utf-8")
print("收到来自于{} {}客户端的信息:".format(client_address[0], client_address[1]), msg)
# print(data)
time.sleep(10)
# 关闭服务器
server.close()

客户端

import socket
client = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
try:
    print("客户端开始连接了……")
    client.connect(("192.168.14.30", 8080))
    print("连接成功")
    msg = client.recv(1024).decode("utf-8")
    print("收到来自于服务器{} {}的信息:".format("192.168.14.30", 8080), msg)
    client.send("怎么可能,我堂堂大罗金仙,寿命永恒,怎会死亡".encode("utf-8"))
except Exception as e:
    print("连接失败,错误信息是", e)
finally:
    client.close()

客户端连接上服务器时,客户端输出信息如下:

客户端开始连接了……
连接成功
收到来自于服务器192.168.14.30 8080的信息: 本服务器来自于阎王殿,告诉你一个不幸的消息,你命不久矣

服务器端输出信息如下:

服务器开始监听了……
收到来自于192.168.14.30 50805客户端的信息: 怎么可能,我堂堂大罗金仙,寿命永恒,怎会死亡

当客户端断开后,服务器端会报错,这需要抛出错误,让程序正常结束

4.多线程的实现

服务器端

def main():
    import socket
    from threading import Thread
    server = socket.socket()
    server.bind(("", 8080))# 绑定服务器的ip 当然也可将服务器的套接字当成一个参数传入
    server.listen(10)
    socket_client, socket_address = server.accept()
    socket_client.send("你已连接到服务器,请注意您的言谈举止".encode("utf-8"))
    t1 = Thread(target=send_msg, args=[socket_client])
    t2 = Thread(target=rec_msg, args=[socket_client])
    t1.start()
    t2.start()
    server.close()


def send_msg(client):
    try:
        while True:
            client.send("\n".encode("utf-8"))
            client.send(input("").encode("utf-8"))
    except Exception as e:
        print("退出连接")
    finally:
        close_resource(client)


def rec_msg(client):
    try:
        while True:
            print(client.recv(1024).decode("utf-8"))
    except Exception as e:
        print("退出连接")
    finally:
        close_resource(client)


def close_resource(client):
    if client is not None:
        client.close()

客户端

# 传入服务器的套接字
def main(ip):
    import socket
    from threading import Thread
    client = socket.socket()
    client.connect(ip)
    print("连接成功")
    print(">:", client.recv(1024).decode("utf-8"))
    t1 = Thread(target=send_msg, args=[client])
    t2 = Thread(target=rec_msg, args=[client])
    t1.start()
    t2.start()


def send_msg(client):
    try:
        while True:
            client.send("\n".encode("utf-8"))
            client.send(input("").encode("utf-8"))

    except Exception as e:
        print("退出连接")
    finally:
        close_resource(client)


def rec_msg(client):
    try:
        while True:
            print(client.recv(1024).decode("utf-8"))
    except Exception as e:
        print("退出连接")
    finally:
        close_resource(client)


def close_resource(client):
    if client is not None:
        client.close()


main(("192.168.14.30", 8080))
由于客户端的退出会导致服务器端出错这里做了抛出错误的处理。



猜你喜欢

转载自blog.csdn.net/qwerLoL123456/article/details/81040992
今日推荐