欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

网络编程[第一篇]基于tcp协议的套接字编程

程序员文章站 2022-04-12 11:43:54
将服务端-客户端的连接比作双方打电话的过程 2019-07-24 一.客户端 主动的一方: 客户端实例化一个socket对象--> 主动像服务端发送连接请求--> (服务端接受请求后即可进行数据传输--> )请求成功后发送信息--> (服务端收到数据信息后反馈一个数据信息给客户端,确认操作成功--> ......

将服务端-客户端的连接比作双方打电话的过程

 2019-07-24

一.客户端

主动的一方:

客户端实例化一个socket对象--> 主动像服务端发送连接请求--> (服务端接受请求后即可进行数据传输--> )请求成功后发送信息--> (服务端收到数据信息后反馈一个数据信息给客户端,确认操作成功--> )关闭进程

####

——手机通话过程

买手机——>打电话——>说话(发信息)——>听对面说话(收信息)——>沟通完成后挂电话

import socket

#买手机  --  套接字家族 | 端口协议
phone = socket.socket(socket.af_inet,socket.sock_stream)

#直接打电话  连接服务端  --  给一个地址- ip | 端口号
phone.connect(('127.0.0.1',1000))

#接通电话后发信息
phone.send('hello'.encode('utf-8'))

#接收反馈信息  指定一次接收的量
data = phone.recv(100)
print('信息为: ',data)

#关机
phone.close()

 

二.服务端

被动的一方:

实例化一个socket对象--> *设置一个监听地址(提供一台电脑的唯一标识—ip+端口号)*-->*设置最大监听数量*-->

接受客户端来的一个连接请求--> 连接成功后接收客户端发来的信息--> 发送反馈信息给客户端--> 关闭该连接请求(可能不止一个连接请求)--> 没有连接请求后关闭进程

####

——手机通话过程

买电话——>*买一张电话卡(唯一一台设备)【提供给客户端一个地址来连接服务端】*——>*开机(处于监听状态,有一个最大监听数量)*——>

接一个电话——>接收到对方的信息——>回复一个信息——>打完电话后挂断电话——>关机(不再监听)

import socket

#买手机  --  套接字家族 | 端口协议
phone = socket.socket(socket.af_inet,socket.sock_stream)

#买电话卡  --  监听一个地址- ip | 端口号
phone.bind(('127.0.0.1',1000))

#开机  指定监听的最大数量   **backlog -- 半连接池**所有的电话均在其中等待
phone.listen(5)

#等电话-接电话  电话接通后会得到(sock--一个socket对象, addr--客户端地址) 
#socket对象 |  客户端地址
link, addr = phone.accept()    #    **从backlog中拿出一个电话接通**
#print('socket对象为:',link)
#print('客户端地址为:',addr)
#》》》

  #socket对象为: <socket.socket fd=628, family=addressfamily.af_inet, type=socketkind.sock_stream, proto=0, laddr=('127.0.0.1', 1000), raddr=('127.0.0.1', 64538)>
  #客户端地址为: ('127.0.0.1', 64538)


#电话接通后接收信息  指定一次接收信息的数量
data = link.recv(100)
print('信息为: ',data)

#接收到信息后,反馈给client端一个信息,以告诉他已成功接收
link.send(data)

#完成一切操作后关掉link,再关机
link.close()
phone.close()

 上述代码互相接发一次,需改进实现多次接发信息

并且只连接一次客户端,对于半连接池中的连接请求信息不再同意连接,这个问题同样需要解决

三.优化——多次接发信息以及多次连接用户

客户端:

import socket

#买手机  --  套接字家族 | 端口协议
phone = socket.socket(socket.af_inet,socket.sock_stream)

#直接打电话  连接服务端  --  给一个地址- ip | 端口号
phone.connect(('127.0.0.1',1001))
#实现多次发送信息
while true:
    #自定义一条信息
    msg = input('输入一条信息:')
   #若信息为空,会导致程序卡死,用if判断跳过此情况
    if not msg:
        continue
    # 接通电话后发信息
    phone.send(msg.encode('utf-8'))
    print('向服务端发送信息:',msg)
    # #接收完整信息
    # accept = 0
    # server_accept = len(msg)
    #接收反馈信息  指定一次接收的量
    data = phone.recv(10)
    print('成功接收到服务端反馈信息 ')
#关机
phone.close()

 

服务端:

import socket

#买手机  --  套接字家族 | 端口协议
phone = socket.socket(socket.af_inet,socket.sock_stream)

#买电话卡  --  监听一个地址- ip | 端口号
phone.bind(('127.0.0.1',1001))

#开机  指定监听的最大数量   **backlog -- 半连接池**所有的电话均在其中等待
phone.listen(5)
#使得服务端完成一次连接后可继续和第二人连接,多次accept
while true:
    #等电话-接电话  电话接通后会得到(return sock, addr)   accept() -> (socket object, address info)
    #tcp链接  |  客户端地址?
    print('等待连接')
    link, addr = phone.accept()    #    **从backlog中拿出一个电话接通**
    #多次接发信息  
    while true:
        #当一个客户端完成通信后客户端主动断开时会导致服务器抛出异常
        try:
            #电话接通后接收信息  指定一次接收信息的数量
            data = link.recv(10)
            print('接受到客户端信息为: ',data)
            #接收到信息后,反馈给client端一个信息,以告诉他已成功接收
            link.send(data)
            print('成功向客户端发送一个反馈信息')
        except exception:
            break
        #完成一切操作后关掉link,再关机
    link.close()
phone.close()

 四.总结——简化

服务端:

1 ss = socket() #创建服务器套接字
2 ss.bind()      #把地址绑定到套接字
3 ss.listen()      #监听链接
4 inf_loop:      #服务器无限循环
5     cs = ss.accept() #接受客户端链接
6     comm_loop:         #通讯循环
7         cs.recv()/cs.send() #对话(接收与发送)
8     cs.close()    #关闭客户端套接字
9 ss.close()        #关闭服务器套接字(可选)

客户端:

1 cs = socket()    # 创建客户套接字
2 cs.connect()    # 尝试连接服务器
3 comm_loop:        # 通讯循环
4     cs.send()/cs.recv()    # 对话(发送/接收)
5 cs.close()            # 关闭客户套接字