基于TCP协议的socket套接字编程

基于TCP协议的socket套接字编程

一、什么是Scoket

Scoket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

所以,我们无需深入理解tc/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。

  • 注意:也有人将scoket说成ip+port,ip是用来标识互联网中的一台主机的位置,而port是用来标识这台机器上的应用程序,ip地址是配置到网卡上的,而port是应用程序开启的,ip和port的绑定就标识了互联网独一无二的一个应用程序,而程序的pid是同一台机器上的不同进程或者线程的标识。

二、基于TCP协议的套接字编程(简单)

客户端

import socket

client = socket.socket()  # 拿电话

# 拨电话,指定服务器ip号和端口号
client.connect(('127.0.0.1',8080))

client.send(b'hello world!')  # 通信发送信息
data = client.recv(1024)  # 接收信息
print(data)
client.close()  # 挂点电话

服务端

import socket


server = socket.socket() # 买手机,不传参数默认用的是TCP协议
# 插入手机卡
server.bind(('127.0.0.1',8080))  # 127.0.0.1本机回还地址 特点:只能识别自己
server.listen(5)  # 开机,半连接池,限制的是请求数

print('start....')
# 接听电话
conn,addr = server.accept() # (三次握手建立的双向连接,(客户端的ip和端口号))

data = conn.recv(1024)  # 最大接收的字节数
print(data)
conn.send(b'hello baby~')  # 发送信息

# 挂掉电话
conn.close()
# 关机
server.close()

三、基于TCP协议的套接字编程(循环)

服务端:

import socket
"""
服务端
    固定的ip地址和port
    24小时不间断提供服务
"""

server = socket.socket()
server.bind(('127.0.0.1',8080))  # 绑定ip和port
server.listen(5)  # 半连接池

while True:
    conn,addr = server.accept() # 等别人来,conn就类似于双向通道
    print(addr)  # ('127.0.0.1',5132)客户端的地址
    while True:
        # 客户端断开连接后,服务器会报错使用异常处理。
        try:
            data = conn.recv(1024)
            print(data)  # b"" 针对mac与linux客户端异常退出之后,服务端不会报错,只会一直收b""
            if len(data) == 0:break
            conn.send(data.upper())
        except ConnectionResetError as e:
            print(e)
            break  # 不中断的话会一直打印错误信息

    conn.close()

客户端

import socket

client = socket.socket()

client.connect(('127.0.0.1',8080))

while True:
    msg = input('>>>:').encode('utf-8')
    if len(msg) == 0:continue
    # if not msg:continue
    client.send(msg)  # 发送的信息可以自己输入
    data = client.recv(1024)
    print(data)

在服务器连接客户端1时,虽然也能监听到客户端2,但不能给客户端2返回消息,将客户端1关闭后即断开连接。给客户端2返回数据。

四、地址占用问题

有的同学在重启服务端时,可能会遇到:

这个是由于你的服务端仍然存在四次挥手的time_wait状态在占用地址。(如果不懂,请深入研究1.tcp三次握手,四次挥手 2.syn洪水攻击 3.服务器高并发情况下会有大量的time_wait状态的优化方法)

# 加入一条socket配置,重用ip和端口
server = socket(AF_INET,SOCK_STREAM)
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
server.bind(('127.0.0.1',8080))
原文地址:https://www.cnblogs.com/zuihoudebieli/p/11331775.html