计算机通讯

SOCKET编程 - 图2

  • mac地址(Media Access Control Address),也称为局域网地址(LAN Address),表示网络设备所在地址,用于在网络中唯一标示一个网卡,一台设备若有一或多个网卡,则每个网卡都需要并会有一个唯一的MAC地址。因为mac比较复杂,所以一般会使用IP来进行定位
  • 通过网线或局域网进行数据传输。

TCP/IP

  • 一个协议族,包含众多网络传输协议,如UDP、TCP、TCP、IP、FTP、SMTP众多协议,因为TCP、IP协议具有代表性,所以取名TCP/IP。其中协议又分为、应用层、传输层、网络层、数据链路层。


    SOCKET编程 - 图3

链路层

  • 将数据处理成数据帧用于传输

网络层

  • IP协议和IP地址
    1. - Internet Protocol 网际互连协议,是[TCP/IP](https://baike.baidu.com/item/TCP%2FIP/214077)体系中的网络层协议
    2. - Internet Protocol Address 互联网协议地址,由322进制组成,对服务器地址进行定位,有IPv4 IPv6版本,现在普遍使用IPv4,地址即将用尽。

传输层

  • 主要作用是定义端口号,确定哪个端口发送数据,哪个端口接收数据。

    • UDP协议:从一个端口发送到另一个端口,但是不管数据对方有没有接收到

    • TCP协议:再UDP协议的基础上保证数据会被正确接收,其中过程有三次握手、四次挥手

      • 三次握手
        • 客户端—>服务段 询问是否可以链接
        • 服务段—>客户端 回应可以链接
        • 客户端—>服务段 链接服务端
      • 四次挥手
        • 客户端—>服务段 通知退出链接
        • 服务段—>客户端 接收退出链接
        • 客户端—>服务段 退出链接
        • 服务段—>客户端 退出链接

应用层

  • 常见的有http,ftp,smtp等,在请求Header中,分别定义了请求数据格式Accept和响应数据格式Content-Type,有了这个规范以后,当对方接收到请求以后就知道该用什么格式来解析
    • 服务端:对请求进行处理,按照请求方要求的格式将数据发送
    • 客户端:收到响应后,按照规定的格式进行解读

Python实现UDP

  • 套接字相当于想要给别人打电话,首先需要一部手机,信息想要传递,就得使用套接字。浏览器即使用套接字进行信息传输。
  • 使用threading多线程,可以让服务器实现多任务

  • 创建套接字

    • socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
    • family=socket.AF_INET IPv4 网络协议的套接字类型
    • type=socket.SOCK_DGRAM 使用UDP传输协议
  • 绑定ip和端口
    • socket.bind((“ip地址”, 10099))
  • 接收数据
    • socket.recv() 返回数据,进制流形式
    • socket.recvfrom() 返回数据,地址,元组形式
  • 发送数据
    • socket.sendto(data=””, address=””)
      • 注意这里传参的时候不用写形参
      • data为进制流格式,同时中文编码utf-8乱码,需要用gbk编码 ```python import socket import threading

class ServerUDP(threading.Thread): def init(self):

  1. # 基础初始化
  2. super().__init__()
  3. # 创建套接字
  4. self.socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
  5. # 绑定本地端口
  6. self.socket.bind(("localhost", 10099))
  7. def __exit__(self, exc_type, exc_val, exc_tb):
  8. # 关闭套接字
  9. self.socket.close()
  10. def run(self):
  11. while True:
  12. # 接收数据
  13. data, addr = self.socket.recvfrom(1024)
  14. data = data.decode('gbk')
  15. print(f"你说: {data} 地址:{addr}")
  16. if data == "退出":
  17. return

class ClientUDP(threading.Thread): def init(self):

  1. # 基础初始化
  2. super().__init__()
  3. # 创建套接字
  4. self.socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
  5. # 绑定本地端口
  6. # self.socket.bind(("localhost", 8888))
  7. def __exit__(self, exc_type, exc_val, exc_tb):
  8. # 关闭套接字
  9. self.socket.close()
  10. def run(self):
  11. while True:
  12. # 发送数据
  13. data = input("输入信息:")
  14. self.socket.sendto(data.encode("gbk"), ("localhost", 10099))
  15. if data == "退出":
  16. return

if name == ‘main‘: s = ServerUDP() s.start()

  1. c = ClientUDP()
  2. c.start()
  1. <a name="QAHL3"></a>
  2. #### TCP服务端
  3. - socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)<br />
  4. - 绑定本地端口
  5. - self.socket.bind(("localhost", 10099))
  6. - 监听连接,最大挂起128个连接,再多了就会拒绝
  7. - socket.listen(128)
  8. - 接收新的套接字
  9. - sock, addr = self.socket.accept()
  10. - sock 新的套接字
  11. - addr 发送信息的地址
  12. - 使用新的套接字来收发信息
  13. ```python
  14. import threading
  15. import socket
  16. class ServerTCP(object):
  17. def __init__(self):
  18. # 基础初始化
  19. super().__init__()
  20. # 创建套接字
  21. self.socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
  22. # 绑定本地端口
  23. self.socket.bind(("localhost", 10099))
  24. # 监听
  25. self.socket.listen(128)
  26. def __exit__(self, exc_type, exc_val, exc_tb):
  27. # 关闭套接字
  28. self.socket.close()
  29. def run(self):
  30. print("服务端已开启")
  31. while True:
  32. # 接受新的套接字 阻塞
  33. sock, addr = self.socket.accept()
  34. print(addr, "已连接")
  35. # 遇到新的连接创建新的线程接收数据
  36. t = threading.Thread(target=self.recieve_data, args=(sock, addr))
  37. t.start()
  38. def recieve_data(self, sock, addr):
  39. while True:
  40. # 接收数据
  41. data = sock.recv(1024)
  42. data = data.decode('gbk')
  43. print(f"地址{addr}: {data} ")
  44. if __name__ == '__main__':
  45. s = ServerTCP()
  46. s.run()

image.png

TCP客户端

  1. import socket
  2. import threading
  3. class ClientTCP(object):
  4. def __init__(self):
  5. # 基础初始化
  6. super().__init__()
  7. # 创建套接字
  8. self.socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
  9. # 绑定本地端口
  10. self.socket.bind(("localhost", 10098))
  11. def __exit__(self, exc_type, exc_val, exc_tb):
  12. # 关闭套接字
  13. self.socket.close()
  14. def run(self):
  15. # 连接服务端
  16. self.socket.connect(("localhost", 10090))
  17. while True:
  18. # 发送数据
  19. data = input("输入信息:")
  20. # 接受数据
  21. self.socket.send(data.encode("gbk"))
  22. print(self.socket.recv(1024))
  23. if data == "退出":
  24. return
  25. if __name__ == '__main__':
  26. c = ClientTCP()
  27. c.run()

image.png