12.socket编程 - TCP

2018-08-22  本文已影响17人  芝麻酱的简书

socket抽象层位于应用层和传输层之间,是对传输层TCP协议和UDP协议的封装,可以让我们无需关心复杂的TCP协议和UDP协议,直接使用socket提供的函数就可以进行网络编程。

屏幕快照 2018-08-23 10.35.34.png

图片来源:https://www.cnblogs.com/Andya/p/7272462.html

客户端步骤:
  1. socket()创建客户端套接字
  2. connect()尝试连接服务器
  3. 进行write()或者read()操作
  4. close()
服务端步骤:
  1. socket()创建服务器套接字
  2. bind()把地址绑定到套接字
  3. listen()监听链接
inf_loop:                               # 服务器无限循环
      cs = ss.accept()                  # 接受客户端链接
      comm_loop:                       # 对接收到的链接 进行通讯循环
              cs.recv()或者cs.send()    # 与客户端对话
      cs.close()                       # 关闭客户端套接字
ss.close()                             # 关闭服务器套接字

1.基础版

服务端实现:

# 服务端
import socket

# 创建服务器套接字 基于网络类型通信而非文件类型   SOCK_STREAM表示TCP协议 流式通信
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定ip地址和端口到套接字 使用元组
server.bind(('127.0.0.1', 8000))

# 监听连接 最大监听数  设置backlog连接池  设置大了可以尽可能的防止syn洪水攻击
server.listen(5)

# 等待 返回建立的链接和地址  收到消息前会一直等待 不执行下面的代码,收到消息后才会向下执行
connection, addr = server.accept()

# 收到的消息 最大1024字节
reveiveMsg = connection.recv(1024)

# 发送消息
connection.send(reveiveMsg)
connection.close()
server.close()

客户端实现:

# 客户端
import socket

# 建立socket 基于网络类型通信而非文件类型   SOCK_STREAM表示TCP协议 流式通信
customer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定ip地址和端口 使用元组
customer.connect(('127.0.0.1', 8000))

customer.send('hello'.encode('utf-8')) # 等同于bytes(data,encoding='utf-8')
data = customer.recv(1024)
print("客户端收到的消息是", data)

2.进化版

服务端循环处理消息:

服务端要做防崩溃处理,来防止客户端断开连接后抛出异常

# import socket
from socket import *
ip_port=('127.0.0.1',8080)
back_log=5
buffer_size=1024

tcp_server=socket(AF_INET,SOCK_STREAM)
tcp_server.bind(ip_port)
tcp_server.listen(back_log)

while True:
    print('服务端开始运行了')
    conn,addr=tcp_server.accept() #服务端阻塞
    print('双向链接是',conn)
    print('客户端地址',addr)

    while True:
        try:
            data=conn.recv(buffer_size)
            print('客户端发来的消息是',data.decode('utf-8'))
            conn.send(data.upper())
        except Exception:
            break
    conn.close()

tcp_server.close()
客户端循环发送:

客户端要做发送消息检测,如果是空消息,会导致应用层从内核内存中获取数据循环等待假死

# import socket
from socket import *
ip_port=('127.0.0.1',8080)
back_log=5
buffer_size=1024

tcp_client=socket(AF_INET,SOCK_STREAM)
tcp_client.connect(ip_port)

while True:
    msg=input('>>: ').strip()
    if not msg:continue
    tcp_client.send(msg.encode('utf-8'))
    print('客户端已经发送消息')
    data=tcp_client.recv(buffer_size)
    print('收到服务端发来的消息',data.decode('utf-8'))

tcp_client.close()

提示

碰到端口占用错误解决方法:

  1. 在socket配置增加重用ip和端口
    在bind前增加:
tcp_client.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
  1. 另一种方法是修改内核
上一篇 下一篇

猜你喜欢

热点阅读