The First Encounter With Socket

date
Oct 4, 2017
slug
first-meet-socket
status
Published
tags
Socket
summary
type
Post

网络基础 TCP/IP

在讨论 Socket 之前,我们得先追本溯源,看看 TCP/IP 是什么。
计算机与网络设备之间的通信,就如大国之间的外交一样,需要一种规则。这种规则就成称为协议(protocol)。计算机网络协议中存在各种各样的内容:从电缆规格到 IP 地址的选定方法、双方建立通信的顺序,以及 Web 页面显示需要处理的步骤,等等。
而与互联网相关联的协议集合总称为 TCP/IP。

TCP/IP 的分层

TCP/IP 按层次分为4层:应用层、传输层、网络层和数据链路层。
notion image

TCP/IP 通信传输流

利用 TCP/IP 协议族进行网络通信时,会通过分层顺序与对方进行通信,发送端从应用层往下走,接收端则从应用层往上走。
notion image

Socket 的基本概念

Socket 是对 TCP/IP 协议族的一种封装,是应用层与TCP/IP协议族通信的中间软件抽象层。它把复杂的 TCP/IP 协议族隐藏在 Socket API 后面,对用户来说,一组简单的接口就是全部,让 Socket 去组织数据,以符合指定的协议。也就是说, TCP/IP 提供给程序员做网络开发所用的接口就是 Socket 编程接口。

利用 Socket 建立网络连接的步骤与基本操作

利用 Socket 建立网络至少需要一对 Socket,其中一个运行于客户端,称为 ClientSocket ,运行于服务端的称为 ServerSocket。
套接字(Socket 的译名)之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。   1、服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。   2、客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。   为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。   3、连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。
notion image

常用的三种 Socket 类型

  • 流式 Socket(SOCK_STREAM):流式是一种面向连接的 Socket,针对于面向连接的 TCP服务应用
  • 数据报式 Socket(SOCK_DGRAM):数据报式 Socket 是一种无连接的 Socket,对应于无连接的UDP 服务应用。
  • Unix 域 Socket (Unix Domain Socket):Socket API原本是为网络通讯设计的,但后来在Socket 的框架上发展出一种IPC机制,就是Unix Domain Socket,用于同一台主机的进程间通讯。虽然网络socket也可用于同一台主机的进程间通讯(通过 loopback 地址127.0.0.1),但是Unix Domain Socket更有效率,不需要经过网络协议栈,只是将应用层数据从一个进程拷贝到另一个进程。

Socket 实践——在 Nodejs 中使用 TCP 套接字编程

服务端代码:
// server.js
const net = require("net");
const host = "127.0.0.1";
const port = 3001;

const server = net
  .createServer(c => {
    console.log(`客户端${c.remoteAddress}:${c.remotePort}已连接`);
     // "data" 事件处理函数
    c.on("data", data => {
      console.log(`来自客户端${c.remoteAddress}:${c.remotePort}的数据:${data}`);
      c.write(`已收到你的数据`);
    });
    c.on("end", () => {
      console.log(`客户端${c.remoteAddress}:${c.remotePort}断开连接`);
    });
  })
  .listen(port, host);
客户端代码:
// client.js
const net = require("net");
const host = "127.0.0.1";
const port = 3001;

const client = new net.Socket();

client.connect(port, host, () => {
  console.log(`连接至${host}:${port}`);
  // 向服务端发送数据
  client.write(`Hello!World!`);

  // "data" 事件处理函数
  client.on("data", data => {
    console.log(`服务器发回: ${data}`);
    client.destroy();
  });
});

client.on("close", function() {
  console.log(`断开连接`);
});


参考

  • 《图解 HTTP》

© Sytone 2021 - 2024