ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## Socket 操作 ![网络七层协议示意图](https://box.kancloud.cn/e2e6beee0280c8aac08794e476f58c52_542x476.jpg) ### TCP/IP 是什么? * TCP/IP 是个协议组,分为三个层次:网络层、传输层和应用层。 * 在网络层有 IP 、ICMP 和 IGMP 协议。 * 在传输层中有 TCP 和 UDP 协议。 * 在应用层有FTP、HTTP、TELNET、SMTP、DNS 等协议。 ### Socket 是什么? Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,一组接口,把复杂的 TCP/IP 协议族隐藏在 Socket 接口后面。 ### Socket 原理 Socket 连接至少需要一对套接字,分为 clientSocket 和 serverSocket。 Socket连接分为3个步骤: * 服务器监听:服务器并不定位具体客户端的套接字,而是时刻处于监听状态。 * 客户端请求:客户端的套接字要描述它要连接的服务器的套接字,提供地址和端口号,然后向服务器套接字提出连接请求。 * 连接确认:当服务器套接字收到客户端套接字发来的请求后,就响应客户端套接字的请求,把服务器端的套接字的描述发给客户端。一旦客户端确认了此描述,就正式建立连接。而服务器套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。 长链接和短链接: * 短链接: 短连接是指 SOCKET 连接后,发送完数据后,马上断开连接。 * 长链接: 长连接是指 SOCKET 连接后,不管是否使用,继续保持链接。 参考链接:[TCP/IP 和 Socket](http://blog.chinaunix.net/uid-9622484-id-3392992.html) ### Socket 发送 HTTP 请求 ``` <?php class HttpClient { const SEP = "\r\n"; // 分隔符 const VERSION = 'HTTP/1.1'; // 协议的版本 private $line = ''; // 请求行 private $body = ''; // 请求正文 private $headers = []; // 请求头 private $uInfo = []; // url信息 public function __construct($url = null) { if ($url) { $this->setUrl($url); } } /** * 设置并解析URL * @param string $url */ public function setUrl($url) { $uInfo = parse_url($url); if (!isset($uInfo['port'])) { $uInfo['port'] = 80; } if (!isset($uInfo['path'])) { $uInfo['path'] = '/'; } $this->uInfo = $uInfo; } /** * 添加请求头信息 * @param string $header */ public function setHeader($header) { $this->headers[] = $header; } /** * GET 请求 * @return array */ public function get() { $this->setLine('GET'); return $this->request(); } /** * POST 请求 * @param array * @return array */ public function post($data = []) { $this->setLine('POST'); $this->setBody($data); $this->setHeader('Content-Type: application/x-www-form-urlencoded'); $this->setHeader('Content-Length: ' . strlen($this->body)); return $this->request(); } /** * 构造请求行信息 * @param string $line GET|POST */ private function setLine($line) { $this->line .= ($line . ' ' . $this->uInfo['path']); if (isset($this->uInfo['query'])) { $this->line .= ('?' . $this->uInfo['query']); } $this->line .= (' ' . self::VERSION); } /** * 构造消息正文 * @param array $data */ private function setBody($data) { if ($data) { $this->body = http_build_query($data); } } /** * 发送数据 * @return array */ private function request() { $this->setHeader('Host: ' . $this->uInfo['host']); $this->setHeader('Connection: close'); $this->setHeader('User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0'); $handle = fsockopen($this->uInfo['host'], $this->uInfo['port']); $str = $this->line . self::SEP; $str .= implode(self::SEP, $this->headers); $str .= self::SEP . self::SEP; if (!empty($this->body)) { $str .= $this->body; } fwrite($handle, $str); $response = ''; while (!feof($handle)) { $response .= fgets($handle); } fclose($handle); $this->response = $response; list($headers, $content) = explode(self::SEP . self::SEP, $response); return [ 'headers' => $headers, 'content' => $content, ]; } } $http = new HttpClient('http://forum-api.local/test'); /* ------------- 发送 GET 请求 ------------ */ $response = $http->get(); var_dump($response['headers']); var_dump($response['content']); exit(); /* ------------- 发送 POST 请求 ------------ */ $data = [ 'name' => 'kate green', 'age' => 12, ]; $response = $http->post($data); var_dump($response['headers']); var_dump($response['content']); ?> ```