基于python实现 TCP服务器与客户端的通讯

TCP协议:

  • 提到TCP,就会有其显著的特点:三次握手 全双工
  • 其三次握手的具体内容形象的一个说法就像两个很客气的人加完了好友之后的反应:
  • A: 我可以加你为好友吗?
  • B:可以呀,我可以加你为好友吗?
  • A:可以呀
    然后就开始没羞没臊的聊天。
    (我记得11-12年那会的QQ确实是这样,双方都有选择是否加对方为好友的选项)
    在这里插入图片描述
    在添加好友之后客户端和服务器之间进行的消息交互是全双工的,有发送有应答
    在这里插入图片描述
    (如果有发送没有应答会怎么样?如果程序设置成没有应答也是没问题的,但是这样就不是TCP的协议了啊!)
    在这里插入图片描述
    客户端流程:
    1.创建socket
    2.链接服务器
    3.接收数据
    4.关闭套接字
    代码:
import socket
def main():
    #pass
    #1.创建套接字 AF_INET 为ipv4   SOCK_STREAM为流控,选择TCP选择的协议
    tcp_client = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)

    server_ip = '192.168.152.1'
    server_port = 7891
    #2.连接服务器
    tcp_client.connect((server_ip,server_port))
    while True:
        #3.收发
        send_content = input('请输入要发送的内容:')
        tcp_client.send(send_content.encode('gbk'))
        recv_content = tcp_client.recv(1024)
        #print(recv_content.encode())
        print(recv_content.decode('gbk'))

    #4.关闭  但是此时这个代码执行不到,
    tcp_client.close()

if __name__ == '__main__':
    main()

服务器端流程:
1.socket创建套接字
2.bind绑定IP和port
3.listen使套接字变为可以被动连接
4.accept等待客户端的连接
5.recv/send接收发送数据

代码:

import socket


def main():
    #1.创建套接字   AF_INET 为ipv4   SOCK_STREAM为流控,选择TCP选择的协议
    tcp_server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
    #2.绑定端口号和IP
    tcp_server.bind(('', 7891))
    #3.listen使套接字变为可以被动连接
    tcp_server.listen(128)
    while True:
        #4.accept等待客户端的连接   阻塞在此阶段,三次握手是在此阶段,在三次握手完成后开始下面的通讯
        new_server_socket, client_addr = tcp_server.accept()
        print(client_addr)
        while True:
            #完成收
            recv_content = new_server_socket.recv(1024)
            print(recv_content.decode('gbk'))
            #如果用网络调试助手进行测试,令调试助手为客户端模式,可以同时打开多个调试口
            # 此时只要关闭一个程序,下一个程序即可与服务器通讯
            if recv_content.decode('gbk'):
                #应答
                send_content = 'hello'
                new_server_socket.send(send_content.encode('gbk'))
                #发出消息和应答就体现在此处
                #pass
            else:
                #new_server_socket.close()
                break
        new_server_socket.close()
    #tcp_server.close()

if __name__ == '__main__':
    main()

至此,第一步不带多线程的TCP通讯完成了,
后续会进行多线程的操作

升级程序:
之前课堂上讲解时,使用netassist模拟client,在server中判断如果收到的信息帧长度为0就断开通讯,那么我们在程序中如何模拟发送长度为0的信息帧呢?一样,只要发出一个空的字符串(并非空格)就可以了,不过在server中通过break跳出内循环就结束了这个通讯了。在复杂的程序中可能遇到其他内容导致server异常结束,我以为是方式不对呢。不过吧,写程序写多了就好了,把那些容易出问题的地方通过抛异常的方式就解决了,try真是个神器
程序如下:
client:
设置发送5次正常字符,第6次发空

import socket
def main():
    #pass
    #1.创建套接字 AF_INET 为ipv4   SOCK_STREAM为流控,选择TCP选择的协议
    tcp_client = socket.socket(family=socket.AF_INET,type=socket.SOCK_STREAM)

    server_ip = '192.168.18.6'
    server_port = 7891
    #2.连接服务器
    tcp_client.connect((server_ip,server_port))
    m = 0
    while m <5:
        #3.收发
        send_content =  'mh'  #input('请输入要发送的内容:')
        tcp_client.send(send_content.encode('gbk'))
        recv_content = tcp_client.recv(1024)
        #print(recv_content.encode())
        print(recv_content.decode('gbk'))
        m += 1
    else:
        send_content = ''
        tcp_client.send(send_content.encode('gbk'))

    #4.关闭  但是此时这个代码执行不到,
    tcp_client.close()

if __name__ == '__main__':
    main()

server 其实并没有变 可以用之前的

import socket


def main():
    #1.创建套接字   AF_INET 为ipv4   SOCK_STREAM为流控,选择TCP选择的协议
    tcp_server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
    #2.绑定端口号和IP
    tcp_server.bind(('', 7891))
    #3.listen使套接字变为可以被动连接
    tcp_server.listen(128)
    while True:
        #4.accept等待客户端的连接   阻塞在此阶段,三次握手是在此阶段,在三次握手完成后开始下面的通讯
        new_server_socket, client_addr = tcp_server.accept()
        print(client_addr)
        while True:
            #完成收
            recv_content = new_server_socket.recv(1024)
            print(recv_content.decode('gbk'))
            #如果用网络调试助手进行测试,令调试助手为客户端模式,可以同时打开多个调试口
            # 此时只要关闭一个程序,下一个程序即可与服务器通讯
            if recv_content.decode('gbk'):
                #应答
                send_content = 'hello'
                new_server_socket.send(send_content.encode('gbk'))
                #发出消息和应答就体现在此处
                #pass
            else:
                #new_server_socket.close()
                break
        new_server_socket.close()
    #tcp_server.close()

if __name__ == '__main__':
    main()

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值