一:TCP客户端搭建:

import socket

def main():
    # 1:创建socket对象
    tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    # 2:建立连接
    tcp_socket.connect(("192.168.70.129",7788))

    #3: 发送数据
    client_data = "我是牛牛,很高兴认识你"
    # send,必须发送二进制数据,如果是Ubuntu--utf8  ,如果是Windows 用gbk
    tcp_socket.send(client_data.encode("utf-8"))

    # 4:接受服务器相应信息
    service_data = tcp_socket.recv(1024)
    print(service_data.decode("utf-8"))

    # 5关闭套接字
    tcp_socket.close()


if __name__ == '__main__':
    main()

二:TCP服务器基本

import socket

def main():

    # 1:创建套接字,socket.AF_INET代表IPV4,SOCK_STREAM代表TCPsocket对象
    tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 特殊:设置端口复用
    tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

    # 2:绑定端口
    tcp_socket.bind(("192.168.70.129",7788))

    # 3:设置监听,128:最大等待连接个数
    tcp_socket.listen(128)

    # 4:等待连接,在没有客户端的时候,accept处于阻塞状态pip
    new_socket, client_msg = tcp_socket.accept()

    # 5:接受收数据

    client_data = new_socket.recv(1024)
    print("客户端发送的数据:" + client_data.decode("utf-8"))

    # 6:发送回数据
    new_socket.send("我是服务器,我收到了你的消息".encode("utf-8"))

    # 7:关闭套接字
    new_socket.close()
    tcp_socket.close()

if __name__ == '__main__':
    main()

# 问题:如果连接一次,客户端强制中断,再次连接服务器端口会被占用.
# 客户端退出后,服务器要等待1~2分钟才能退出.
# 解决方案:设置端口复用----必须在绑定端口之前


# 问题接受到的字节数是发送汉字的三倍???
# utf-8中一个汉字用3个字节

三:服务器比客户端提前关闭:

# 服务器比客户端提前关闭,之前已经通信的仍然可以通信.但是新的通信不能再连接

import socket

def main():

    # 1:创建套接字,socket.AF_INET代表IPV4,SOCK_STREAM代表TCPsocket对象
    tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 特殊:设置端口复用
    tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

    # 2:绑定端口
    tcp_socket.bind(("192.168.70.129",7788))

    # 3:设置监听,128:最大等待连接个数
    tcp_socket.listen(128)

    # 4:等待连接,在没有客户端的时候,accept处于阻塞状态pip
    new_socket, client_msg = tcp_socket.accept()

    # 5:接受收数据

    client_data = new_socket.recv(1024)
    print("客户端发送的数据:" + client_data.decode("utf-8"))

    tcp_socket.close()

    # 6:发送回数据
    new_socket.send("我是服务器,我收到了你的消息".encode("utf-8"))

    # 7:关闭套接字
    new_socket.close()


if __name__ == '__main__':
    main()

四:客户端提前关闭:

# 服务器比客户端提前关闭,之前已经通信的仍然可以通信.但是新的通信不能再连接

# 客户端连接立马关闭输出:
# 客户端发送的数据:

# 原理:客户端关闭后recv解阻塞,此时服务器收到一个空数据.
# 更新版本,如果接受到是空数据就退出

import socket

def main():

    # 1:创建套接字,socket.AF_INET代表IPV4,SOCK_STREAM代表TCPsocket对象
    tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 特殊:设置端口复用
    tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

    # 2:绑定端口
    tcp_socket.bind(("192.168.70.129",7788))

    # 3:设置监听,128:最大等待连接个数
    tcp_socket.listen(128)

    # 4:等待连接,在没有客户端的时候,accept处于阻塞状态pip
    new_socket, client_msg = tcp_socket.accept()

    # 5:接受收数据

    client_data = new_socket.recv(1024)

    # 收到的是二进制不是字符串 所以不能用""进行比较
    # if client_data == "":(错的)
    if len(client_data) == 0:
        print("客户端关闭了,我也关闭")

    else:

        print("客户端发送的数据:" + client_data.decode("utf-8"))

        # 6:发送回数据
        new_socket.send("我是服务器,我收到了你的消息".encode("utf-8"))


    tcp_socket.close()
    # 7:关闭套接字
    new_socket.close()


if __name__ == '__main__':
    main()

五:循环收发消息:

# 我想循环接受一个客户端的消息

import socket


def main():
    # 1:创建套接字,socket.AF_INET代表IPV4,SOCK_STREAM代表TCPsocket对象
    tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 特殊:设置端口复用
    tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

    # 2:绑定端口
    tcp_socket.bind(("192.168.70.129", 7788))

    # 3:设置监听,128:最大等待连接个数
    tcp_socket.listen(128)

    # 4:等待连接,在没有客户端的时候,accept处于阻塞状态pip
    new_socket, client_msg = tcp_socket.accept()

    # 5:接受收数据
    while True:

        client_data = new_socket.recv(1024)


        if len(client_data) == 0:
            print("客户端关闭了,我也关闭")
            break

        else:

            print("客户端发送的数据:" + client_data.decode("utf-8"))

            # 6:发送回数据
            new_socket.send("我是服务器,我收到了你的消息".encode("utf-8"))

        tcp_socket.close()
    # 7:关闭套接字
    new_socket.close()


if __name__ == '__main__':
    main()

六:循环发送消息为多个客户端服务:

# 我想循环接受一个客户端的消息,并且给多个客户端服务

# 缺点:只能第一个结束后,第二个才能服务:
# 本质:


import socket


def main():
    # 1:创建套接字,socket.AF_INET代表IPV4,SOCK_STREAM代表TCPsocket对象
    tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 特殊:设置端口复用
    tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

    # 2:绑定端口
    tcp_socket.bind(("192.168.70.129", 7788))

    # 3:设置监听,128:最大等待连接个数
    tcp_socket.listen(128)

    while True:

        # 4:等待连接,在没有客户端的时候,accept处于阻塞状态pip
        # 当客户端A正在占用new_socket,accept此时处于阻塞状态
        # 当A关闭后,accept解阻塞,再为B服务.
        
        new_socket, client_msg = tcp_socket.accept()
        print("客户端:", client_msg)

        # 5:接受收数据
        while True:

            client_data = new_socket.recv(1024)


            if len(client_data) == 0:
                print("客户端关闭了,我也关闭")
                break

            else:

                print("客户端发送的数据:" + client_data.decode("utf-8"))

                # 6:发送回数据
                new_socket.send("我是服务器,我收到了你的消息".encode("utf-8"))

            tcp_socket.close()
    # 7:关闭套接字
    new_socket.close()


if __name__ == '__main__':
    main()

七:最终代码:

# 思路:之前版本,我只能一个接着一个来,是因为accept阻塞.
# 我们把接收客户端的作为主线程,把给客户端服务的作为子线程就解决这个问题了.
import threading
import socket

def new_thread(new_socket):
    # 5:接受收数据
    while True:

        client_data = new_socket.recv(1024)

        if len(client_data) == 0:
            print("客户端关闭了,我也关闭")
            break

        else:

            print("客户端发送的数据:" + client_data.decode("utf-8"))

            # 6:发送回数据
            new_socket.send("我是服务器,我收到了你的消息".encode("utf-8"))

    new_socket.close()

def main():
    # 1:创建套接字,socket.AF_INET代表IPV4,SOCK_STREAM代表TCPsocket对象
    tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 特殊:设置端口复用
    tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

    # 2:绑定端口
    tcp_socket.bind(("192.168.70.129", 7788))

    # 3:设置监听,128:最大等待连接个数
    tcp_socket.listen(128)

    while True:

        # 4:等待连接,在没有客户端的时候,accept处于阻塞状态pip
        # 当客户端A正在占用new_socket,accept此时处于阻塞状态
        # 当A关闭后,accept解阻塞,再为B服务.

        new_socket, client_msg = tcp_socket.accept()
        print("客户端:", client_msg)

        t1 = threading.Thread(target=new_thread,args=(new_socket,))

        # 设置成守护主线程
        t1.daemon = True

        t1.start()



    tcp_socket.close()


if __name__ == '__main__':
    main()