Socket网络编程初探
admin
2023-03-25 13:21:33
0

MarkdownPad Document

Socket网络编程初探

客户端/服务器架构

  • 即C/S架构,其实web服务在某种意义上也算是C/S架构

  • 一个特点是服务器端持续运行对外提供服务

为何学习socket一定要先学习互联网协议:

  1. C/S架构的软件是基于网络进行通信的

  2. 网络的核心就是一堆协议,即标准,想要开发一款基于网络通信的软件就必须遵循这些标准

  3. socket是处在应用层和传输层中间的一组接口

Socket网络编程初探

说到这,那么socket到底是个什么呢?Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在socket接口后面,对用户来说,一组简单的接口就是全部,让socket去组织数据,以符合指定的协议。所以,无需深究TCP/UDP协议,socket已经为我们封装好了

基于文件类型的套接字家族:AFUNIX基于网络类型的套接字家族:AFINET

套接字的工作流程

Socket网络编程初探

先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束

服务端套接字函数

s.bind()    绑定(主机,端口号)到套接字
s.listen()  开始TCP监听
s.accept()  被动接受TCP客户的连接,(阻塞式)等待连接的到来

客户端套接字函数

s.connect()     主动初始化TCP服务器连接
s.connect_ex()  connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

公共用途的套接字函数

s.recv()            接收TCP数据
s.send()            发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
s.sendall()         发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
s.recvfrom()        接收UDP数据
s.sendto()          发送UDP数据
s.getpeername()     连接到当前套接字的远端的地址
s.getsockname()     当前套接字的地址
s.getsockopt()      返回指定套接字的参数
s.setsockopt()      设置指定套接字的参数
s.close()           关闭套接字

面向锁的套接字方法

s.setblocking()     设置套接字的阻塞与非阻塞模式
s.settimeout()      设置阻塞套接字操作的超时时间
s.gettimeout()      得到阻塞套接字操作的超时时间

面向文件的套接字的函数

s.fileno()          套接字的文件描述符
s.makefile()        创建一个与该套接字相关的文件

代码示例:

服务端

from socket import *
phone=socket(AF_INET,SOCK_STREAM)
phone.bind(('127.0.0.1',8081))
phone.listen(5)

conn,addr=phone.accept()
while True:
    data=conn.recv(1024)
    print('server===>')
    print(data)
    conn.send(data.upper())
conn.close()
phone.close()

客户端

from socket import *

phone=socket(AF_INET,SOCK_STREAM)
phone.connect(('127.0.0.1',8081))

while True:
    msg=input('>>: ').strip()
    phone.send(msg.encode('utf-8'))
    print('client====>')
    data=phone.recv(1024)
    print(data)

注意:这时候当客户端输入消息为空的话程序会卡住,那是因为无论是服务端还是客户端都要到自己所在主机缓冲区去拿消息,因为这时发送为空,服务端根本就不会有任何反应,所以客户端的缓冲区也不会有任何内容,所以这时它会一直徒劳的等待。。。

这时的解决办法当然要在客户端想办法,很简单,我们不让客户端发送空消息即可,在send()方法之前加判断:

if not msg :continue

你肯定以为这个时候就完事了,这时请尝试断开客户端链接试试。。。试想,既然作为服务端,顾名思义就是要持续不断的为不同的客户端持续的提供服务,怎么能一个客户端用完即结束呢?解决方案如下:

while True: #链接循环
    conn,addr=phone.accept() 

    print('电话线路是',conn)
    print('客户端的手机号是',addr)

    while True: #通信循环
        try: 
            data=conn.recv(1024)
            if not data:break 
            print('客户端发来的消息是',data)

            conn.send(data.upper())
        except Exception:
            break

    conn.close()

phone.close()

注意:可能会有人遇到重启服务端时Address already in use 的情况,这个是由于你的服务端仍然存在四次挥手的timewait状态在占用地址(如果不懂,请深入研究1.tcp三次握手,四次挥手 2.syn洪水*** 3.服务器高并发情况下会有大量的timewait状态的优化方法)

解决方法:

#加入一条socket配置,重用ip和端口

phone=socket(AF_INET,SOCK_STREAM)
phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
phone.bind(('127.0.0.1',8080))

相关内容

热门资讯

特朗普下令不打了,美国的“余粮... 可以说戛然而止,快得让很多人都无法适应。前两周,每一天美国都要打击伊朗一通。就在7月24日白宫会议前...
穆杰塔巴最新表态:支持黎真主党 △伊朗最高领袖穆杰塔巴·哈梅内伊(资料图)当地时间7月26日晚,伊朗最高领袖穆杰塔巴·哈梅内伊对黎巴...
美军瘫痪一艘驶向伊朗的油轮,特... 美国总统特朗普虽下令暂停打击伊朗,但美军仍在执行对霍尔木兹海峡的封锁任务。针对美军瘫痪一艘驶向伊朗油...
“小牌大耍”的底气到底是哪里来... 澎湃首席评论员 李平这两天,“艺人李权哲乘高铁占座事件”在网上引发热议,该艺人参加的活动主办方曾发布...
越南籍船舶南海遇险沉没,中方已... 据凤凰卫视报道,一艘越南船舶7月24日夜间在越南庆和以东220海里附近遇险沉没,船上共62名越南籍人...
李权哲占座、蒙面、装死:娱乐圈... 你买了一张高铁一等座的票,找到自己的位置,18A。有人坐着。你拿出手机看了眼购票记录——没错,18A...
杭州景区咖啡店闯入1条幼蛇,仅... 夏天气温高、湿度大,蛇类活动进入高峰期,千万别被“小蛇无害”的刻板印象骗了!有些幼蛇看着迷你可爱,实...
AI开源公开信签署企业增至50... IT之家 7 月 26 日消息,英伟达、微软、IBM、Meta 等 25 家美国科技企业本周(7 月...
南阳快手短视频代运营企业的服务... 在短视频平台快速发展的背景下,企业通过快手等渠道进行内容运营已成为常见的市场动作。对于希望借助短视频...
普通人该如何跟上科技发展的步伐 这个被称作科技的词汇, 听起来既有宏大之感, 又颇为遥远, 好似仅仅归属于在实验室里专心致志钻研的科...