使用websocket解决客户端和服务器TCP长链接拆包粘包问题

客户端和服务器使用TCP进行长连接发送接收数据时,会出现粘包、拆包现象。因为TCP传输数据时是以流方式传输的,消息并非一包一包发送。传统的解决此问题的方式是发送端在发送数据前,先发送一个固定字节(例如4字节)的包含数据长度的消息。接收端先接收4字节数据,获取要接收的数据的长度,然后再获取该长度的数据。这就使编码流程复杂化。

websocket实现了客户端和服务器之间的TCP长链接,全双工通信。并且websocket内部的帧结构处理了粘包,拆包的问题,使我们不需要手动处理TCP层面的拆包和粘包问题。所以有客户端和服务器之间的长链接需求,可以集成现有的websocket库,简化编码流程。

下面就以c++客户端和golang服务端为例来说明。

c++客户端使用的websocket来源于libpoco库(git@github.com:pocoproject/poco.git)。

golang 服务端使用的websocket来源于(github.com/gorilla/websocket)。

服务器golang代码

package main

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{}

type WsTransport struct {
	conn  *websocket.Conn
	ready bool
}

func NewWsTransport() *WsTransport {
	ws := &WsTransport{ready: false}
	return ws
}

func (ws *WsTransport) Handle(w http.ResponseWriter, r *http.Request) {
	ws.conn, _ = upgrader.Upgrade(w, r, nil)
	ws.ready = true
	for {
		t, buff, err := ws.conn.ReadMessage()
		fmt.Printf("%d, %s, %v\n", t, string(buff), err)
		if err != nil {
			return
		}
	}
}

func (ws *WsTransport) SendMessage(msg string) {
	if !ws.ready {
		return
	}
	err := ws.conn.WriteMessage(1, []byte(msg))
	if err != nil {
		fmt.Println(err)
		return
	}
}

func main() {
	ws := NewWsTransport()
	http.HandleFunc("/ws", ws.Handle)
	go SendMessage(ws)
	log.Fatal(http.ListenAndServe("localhost:8800", nil))
}

func SendMessage(ws *WsTransport) {
	for {
		ws.SendMessage("message from server")
		time.Sleep(1 * time.Second)
	}
}

客户端c++代码 (poco的头文件和库需编译和继承到项目中)

#include <iostream>
#include <set>
#include <chrono>
#include <memory>
#include <thread>

#include "Poco/Net/WebSocket.h"
#include "Poco/Net/HTTPClientSession.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/ServerSocket.h"



using namespace std;
using namespace Poco;

class UaTransport {
public:
	UaTransport(const std::string& remote_ip, uint16_t port):cs_(remote_ip, port) {
		MakeWebSocket();
		th_ = std::thread(&UaTransport::RecvWork, this);
	}
	virtual ~UaTransport(){}

	int SendFrame(const std::string& payload) {
		return ws_->sendFrame(payload.data(), (int)payload.size());
	}
	void StopRecv() {
		stop_ = true;
		th_.join();
	}
private:
	void MakeWebSocket() {
		Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, "/ws", Poco::Net::HTTPRequest::HTTP_1_1);
		Poco::Net::HTTPResponse response;

		ws_ = std::make_unique<Poco::Net::WebSocket>(cs_, request, response);
		ws_->setBlocking(false);
		ws_->setSendBufferSize(256 * 1024);
		ws_->setReceiveBufferSize(256 * 1024);
	}
	void RecvWork() {
		constexpr int bufsize = 256 * 1024;
		auto buffer = std::make_unique<char>(bufsize);
		int flags;
		while (!stop_) {
			ws_->poll(10000000, Poco::Net::Socket::SELECT_READ);
			int n = ws_->receiveFrame(buffer.get(), bufsize, flags);
			std::cout << std::string(buffer.get()) << std::endl;
		}
	}
private:
	bool stop_{ false };
	Poco::Net::HTTPClientSession cs_;
	std::unique_ptr<Poco::Net::WebSocket> ws_;
	std::thread th_;
};

int main(int argc, char** argv) {
	std::string ip{ "127.0.0.1" };
	uint16_t port = 8800;
	auto tr = std::make_unique<UaTransport>(ip, port);
	
	while (1) {
		std::this_thread::sleep_for(std::chrono::seconds(1));
		std::string str{ "message from client" };
		tr->SendFrame(str);
	}
	return 0;
}

先运行服务器,再运行客户端,可以看到客户端和服务器都能收到对方发送来的数据。

<think>好的,用户需要2024年版的Java面试资料或宝典。首先,我得确认目前最新的资源是什么。虽然2024年的可能还没完全出来,但可以推荐最近更新的或者经典持续更新的资料。 用户提到的引用里有数据结构算法的书籍,比如《Data Structures and Algorithms: Deep Dive Using Java》,这可能是一个好的起点。另外,引用中的网站链接可能有最新的资源,比如GitHub上的中文版最佳网站列表,里面可能有程序员分享的最新面试资料。 接下来,我需要考虑用户可能需要的具体内容。Java面试通常括核心Java、多线程、集合框架、JVM、设计模式、Spring框架等。此外,算法数据结构也是重点,比如快速排序、哈希表等。因此,推荐的资料应该涵盖这些方面。 还要注意书籍的版本,是否有2023或2024年的更新版。例如,《Effective Java》第三版虽然发布于2018年,但仍是经典,可能还在推荐列表中。另外,一些在线平台如LeetCode、牛客网会有最新的面试题库,这些也是重要的资源。 用户可能还希望有实战项目或系统设计的内容,所以像《Cracking the Coding Interview》这样的书虽然主要针对算法,但也是必备的。此外,GitHub上的开源项目或指南,如“Java设计模式精讲”可能帮助用户深入理解。 需要检查引用中的资料是否有最新版,或者是否有替代的新资源。例如,引用1提到的书籍是否有2024版,或者是否有类似的更新指南。如果没有,可能需要推荐常青资源,并建议用户关注某些网站或社区获取最新信息。 最后,整理这些资源,分门别类,确保结构清晰,让用户能一步步找到所需资料。同时,提醒用户结合实践理论,参与刷题模拟面试,这样准备更充分。</think>### 2024年Java面试资料与宝典推荐 #### 一、经典书籍(持续更新版本) 1. **《Effective Java》第三版** 涵盖Java 8/9/10特性,深入讲解编码规范与设计模式,是面试核心考点[^1]。 2. **《Java编程思想》(Thinking in Java)** 系统讲解Java语法与面向对象思想,适合夯实基础。 3. **《深入理解Java虚拟机》第三版** 详解JVM内存模型、垃圾回收机制,高频面试章节如类加载、性能调优。 #### 二、算法与数据结构专项 1. **《Cracking the Coding Interview》第六版** 含189道编程题及解法,覆盖快速排序、动态规划等高频考点[^1]。 ```java // 示例:快速排序实现 public void quickSort(int[] arr, int low, int high) { if (low < high) { int pi = partition(arr, low, high); quickSort(arr, low, pi - 1); quickSort(arr, pi + 1, high); } } ``` 2. **LeetCode与牛客网题库** 2024年新增题型聚焦并发编程(如CompletableFuture)Java 17特性(如模式匹配)[^2]。 #### 三、系统设计与架构 1. **《Head First设计模式》第二版** 结合Spring框架解读单例、工厂等模式,含实际项目案例分析。 2. **《微服务架构设计模式》** 针对分布式系统面试题,如CAP定理、服务熔断等[^1]。 #### 四、最新实战资源 1. **GitHub开源项目** - **「Java面试指南」仓库**:含2024年大厂真题解析(如Redis缓存穿透解决方案)[^3]。 - **「Spring Boot实战项目集」**:整合Spring Cloud Alibaba与Kubernetes部署方案。 2. **在线课程平台** - **极客时间《Java核心技术面试精讲》**:2024年新增Java 21虚拟线程(Virtual Threads)详解。 #### 五、备考策略 1. **分阶段学习计划** - 第一阶段:2周通读《Effective Java》核心章节(如泛型、Lambda) - 第二阶段:3周刷LeetCode Hot 100 + 牛客网Java专项 - 第三阶段:1周模拟面试(使用Pramp或AlgoExpert平台) 2. **避坑指南** - 避免过度关注冷门语法(如Java Flight Recorder),优先掌握高频考点(如HashMap扩容机制) - 警惕过时资料中已被废弃的技术(如Java EE中的Corba)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值