WebSocket 是一种通信协议,它在单个 TCP 连接上提供全双工通信通道。以下是有关 WebSocket 的一些关键点:
-
全双工通信:与 HTTP 不同,HTTP 是一种请求-响应协议,而 WebSocket 允许客户端和服务器之间的双向通信。双方可以同时发送和接收数据。
-
连接生命周期:
- 握手:WebSocket 连接以 HTTP 握手开始,客户端请求升级到 WebSocket 协议。如果服务器同意,则建立连接。
- 打开:一旦连接建立,它将保持打开状态,允许持续通信。
- 消息:双方可以随时以消息的形式发送数据。
- 关闭:客户端或服务器都可以关闭连接。
-
低延迟:与 HTTP 轮询或长轮询相比,WebSocket 连接设计为低延迟且更高效,适用于实时通信。
-
应用场景:WebSocket 广泛应用于需要实时更新的应用程序,如在线聊天应用、网络游戏、实时金融数据推送和协同编辑。
-
API:WebSocket 得到了大多数现代浏览器的支持,可以使用简单的 JavaScript API 在客户端上使用。在服务器端,不同编程语言中有各种库和框架支持 WebSocket。
以下是如何使用 WebSocket 的简单示例:
当然,这里是使用 C 语言实现 WebSocket 客户端和服务器的示例。为了简化示例,假设使用 libwebsockets
库。你可以从 libwebsockets 网站获取更多信息,并安装该库。
客户端(C 语言)
c
#include <libwebsockets.h>
#include <string.h>
static int callback(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len) {
switch (reason) {
case LWS_CALLBACK_CLIENT_ESTABLISHED:
lwsl_user("Connection established\n");
lws_callback_on_writable(wsi);
break;
case LWS_CALLBACK_CLIENT_RECEIVE:
lwsl_user("Received: %s\n", (char *)in);
break;
case LWS_CALLBACK_CLIENT_WRITEABLE:
{
char *msg = "Hello Server!";
unsigned char buf[LWS_PRE + strlen(msg)];
memcpy(&buf[LWS_PRE], msg, strlen(msg));
lws_write(wsi, &buf[LWS_PRE], strlen(msg), LWS_WRITE_TEXT);
}
break;
case LWS_CALLBACK_CLIENT_CLOSED:
lwsl_user("Connection closed\n");
break;
default:
break;
}
return 0;
}
static struct lws_protocols protocols[] = {
{ "example-protocol", callback, 0, 1024 },
{ NULL, NULL, 0, 0 }
};
int main(void) {
struct lws_context_creation_info info;
memset(&info, 0, sizeof(info));
info.port = CONTEXT_PORT_NO_LISTEN;
info.protocols = protocols;
struct lws_context *context = lws_create_context(&info);
if (!context) {
lwsl_err("lws_create_context failed\n");
return 1;
}
struct lws_client_connect_info ccinfo = {0};
ccinfo.context = context;
ccinfo.address = "localhost";
ccinfo.port = 8080;
ccinfo.path = "/";
ccinfo.host = lws_canonical_hostname(context);
ccinfo.origin = "origin";
ccinfo.protocol = protocols[0].name;
struct lws *wsi = lws_client_connect_via_info(&ccinfo);
if (!wsi) {
lwsl_err("lws_client_connect_via_info failed\n");
return 1;
}
while (lws_service(context, 1000) >= 0);
lws_context_destroy(context);
return 0;
}
服务器(C 语言)
c
#include <libwebsockets.h>
#include <string.h>
static int callback(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len) {
switch (reason) {
case LWS_CALLBACK_ESTABLISHED:
lwsl_user("Connection established\n");
break;
case LWS_CALLBACK_RECEIVE:
lwsl_user("Received: %s\n", (char *)in);
{
char *msg = "Hello Client!";
unsigned char buf[LWS_PRE + strlen(msg)];
memcpy(&buf[LWS_PRE], msg, strlen(msg));
lws_write(wsi, &buf[LWS_PRE], strlen(msg), LWS_WRITE_TEXT);
}
break;
case LWS_CALLBACK_CLOSED:
lwsl_user("Connection closed\n");
break;
default:
break;
}
return 0;
}
static struct lws_protocols protocols[] = {
{ "example-protocol", callback, 0, 1024 },
{ NULL, NULL, 0, 0 }
};
int main(void) {
struct lws_context_creation_info info;
memset(&info, 0, sizeof(info));
info.port = 8080;
info.protocols = protocols;
struct lws_context *context = lws_create_context(&info);
if (!context) {
lwsl_err("lws_create_context failed\n");
return 1;
}
while (lws_service(context, 1000) >= 0);
lws_context_destroy(context);
return 0;
}
在这两个示例中,我们分别创建了一个 WebSocket 客户端和服务器,并通过 libwebsockets
库进行
当然,这里是使用 Java 实现 WebSocket 客户端和服务器的示例。我们将使用 Java 的标准库 javax.websocket
来实现。
客户端(Java)
首先,确保你有 javax.websocket
库。它包含在 Java EE 或者可以通过 Maven 获取:
xml
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
</dependency>
以下是 WebSocket 客户端的示例:
java
import javax.websocket.ClientEndpoint;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.ContainerProvider;
import javax.websocket.WebSocketContainer;
import java.net.URI;
@ClientEndpoint
public class WebSocketClient {
@OnOpen
public void onOpen(Session session) {
System.out.println("Connected to server");
try {
session.getBasicRemote().sendText("Hello Server!");
} catch (Exception e) {
e.printStackTrace();
}
}
@OnMessage
public void onMessage(String message) {
System.out.println("Received message: " + message);
}
public static void main(String[] args) {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
String uri = "ws://localhost:8080/websocket";
System.out.println("Connecting to " + uri);
try {
container.connectToServer(WebSocketClient.class, URI.create(uri));
} catch (Exception e) {
e.printStackTrace();
}
}
}
服务器(Java)
服务器端我们使用 javax.websocket
和一个嵌入式的 Jetty 服务器。首先,添加 Maven 依赖项:
xml
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-server-api</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.35.v20201120</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>9.4.35.v20201120</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
<version>9.4.35.v20201120</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>javax-websocket-server-impl</artifactId>
<version>9.4.35.v20201120</version>
</dependency>
以下是 WebSocket 服务器的示例:
java
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
@ServerEndpoint("/websocket")
public class WebSocketServer {
@OnOpen
public void onOpen(Session session) {
System.out.println("Client connected");
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("Received message: " + message);
try {
session.getBasicRemote().sendText("Hello Client!");
} catch (Exception e) {
e.printStackTrace();
}
}
@OnClose
public void onClose(Session session) {
System.out.println("Connection closed");
}
public static void main(String[] args) throws Exception {
Server server = new Server(8080);
ContextHandler context = new ContextHandler();
context.setContextPath("/");
server.setHandler(context);
WebSocketServerContainerInitializer.configureContext(context);
context.addServlet(WebSocketServer.class, "/websocket");
server.start();
server.join();
}
}
在这个示例中,我们创建了一个简单的 WebSocket 服务器,并使用嵌入式 Jetty 服务器运行。客户端连接到服务器后,发送 "Hello Server!" 消息,服务器接收到消息后回复 "Hello Client!"。
要运行这些示例,请确保添加了相应的依赖项,并根据需要调整你的项目设置。