1.springboot websocket服务端
话不多说先上代码,首先是配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
//webSocket配置类
@Configuration
@EnableWebSocket
public class WebsocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
然后是websocket服务端 用username区分是哪个客户端,然后后续客户端连上之后可以通过这个给客户端发消息,我是用json的格式发送。
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.junit.platform.commons.util.StringUtils;
import org.springframework.stereotype.Component;
import javax.imageio.ImageIO;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.awt.*;
import java.awt.image.RenderedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.atomic.AtomicInteger;
@Component
@ServerEndpoint("/websocket/{username}") //暴露的ws应用的路径
@Slf4j
public class MyWebSocket {
//存储每一个客户端会话信息的线程安全的集合
public static final ConcurrentSkipListMap<String,Session> sessions = new ConcurrentSkipListMap<>();
//使用线程安全的计数器,记录在线数
private static final AtomicInteger onlineCount = new AtomicInteger(0);
private SeekableByteChannel byteChannel;
/**
* 客户端与服务端连接成功
* @param session
* @param username
*/
@OnOpen
public void onOpen(Session session, @PathParam("username") String username){
/*
do something for onOpen
与当前客户端连接成功时
*/
if(sessions.containsKey(username)){
return;
}
//存储会话信息
sessions.put(username,session);
//计数+1
int cnt = onlineCount.incrementAndGet();
//打印日志
log.info(username + "连接加入,当前连接数为:" + cnt);
//改为json格式数据 方便客户端区别消息或者指令
JSONObject msgJson = new JSONObject();
msgJson.put("key","msg");
msgJson.put("msg","连接成功");
//给客户端发消息
this.sendMessage(session, username,msgJson.toString());
}
/**
* 客户端与服务端连接关闭
* @param session
* @param username
*/
@OnClose
public void onClose(Session session,@PathParam("username") String username){
/*
do something for onClose
与当前客户端连接关闭时
*/
//删除会话信息
sessions.remove(username);
//计数-1
int cnt = onlineCount.decrementAndGet();
//打印日志
log.info(username + "连接关闭,当前连接数为:" + cnt);
}
/**
* 客户端与服务端连接异常
* @param error
* @param session
* @param username
*/
@OnError
public void onError(Throwable error,Session session,@PathParam("username") String username) {
//打印日志
log.error("发生错误:Username:" + error.getMessage() + username);
}
/**
* 客户端向服务端发送消息
* @param message
* @param username
* @throws IOException
*/
@OnMessage
public void onMsg(Session session,String message,@PathParam("username") String username) throws IOException {
/*
do something for onMessage
收到来自当前客户端的消息时
*/
//打印日志
log.info("来自"+username+"的消息:" + message);
//给客户端发消息
this.sendMessage(session,username, "收到消息,消息内容:" + message);
}
@OnMessage
public void onMsg(byte[] byteBuffer, Session session, @PathParam("username") String username) throws IOException {
System.out.println("接收到消息");
try {
// 将字节数组转换为图片对象
Image image = ImageIO.read(new ByteArrayInputStream(byteBuffer));
// 在这里可以对接收到的图片进行处理或保存
ImageIO.write((RenderedImage) image,"jpg",new File("123.jpg"));
System.out.println("Received image: " + image);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 发送消息
* @param session
* @param message
*/
public void sendMessage(Session session,String username,String message) {
if(StringUtils.isBlank(username)){
return;
}
if(session == null){
session = sessions.get(username);
}
//发送消息
session.getAsyncRemote().sendText( message);
}
/**
* 群发消息
* @param message
* @param message
*/
public void sendMessage(String message) {
if(sessions.keySet().size() <= 0)
return;
sessions.keySet().stream().forEach(key -> {
Session session = sessions.get(key);
//判断连接是否开着
if(session.isOpen()){
//一个一个发
this.sendMessage(session, key,message);
}
});
}
}
然后是我手写的一个小的测试控制器类
import com.alibaba.fastjson.JSONObject;
import com.wsdn.websocketdemo.command.CommonStand;
import com.wsdn.websocketdemo.socket.MyWebSocket;
import org.junit.platform.commons.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import java.util.Scanner;
/**
* websocket 控制器
*/
@RestController
@RequestMapping("/wsk")
public class WskController {
@Autowired
private MyWebSocket myWebSocket;
@PostMapping("/sendMsg/{username}")
public String sendMsgToClient(@RequestBody Map<String,String> msgMap,@PathVariable String username){
try {
System.out.println(msgMap.get("msg"));
myWebSocket.sendMessage(null,username,msgMap.get("msg"));
} catch (Exception e) {
return "没有与" + username + "建立连接";
}
return "success";
}
/**
* 发送命令
* @param username
* @return
*/
@GetMapping("/command/{username}/{key}")
public String sendCommand(@PathVariable("key") String key,@PathVariable("username") String username){
try {
if(StringUtils.isNotBlank(key) && StringUtils.isNotBlank(username)){
if(CommonStand.getEnum(key) != null){
CommonStand anEnum = CommonStand.getEnum(key);
JSONObject json = new JSONObject();
json.put("key",key);
json.put("msg",anEnum.getMsg());
myWebSocket.sendMessage(null,username,json.toString());
return "success";
}
}else{
return "没有与" + username + "建立连接";
}
} catch (Exception e) {
return "没有与" + username + "建立连接";
}
return "success";
}
}
2.Android客户端 websocket
import android.app.Service;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dji.sdk.sample.R;
import com.dji.sdk.sample.internal.view.PresentableView;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import androidx.annotation.NonNull;
import de.tavendo.autobahn.WebSocketConnection;
import de.tavendo.autobahn.WebSocketException;
import de.tavendo.autobahn.WebSocketHandler;
public class WebsocketView extends LinearLayout implements View.OnClickListener, PresentableView {
public WebsocketView(Context webContext){
super(webContext);
initUI();
}
private WebSocketConnection mConnect = new WebSocketConnection();
/**
*
按钮 变量
*/
// 连接 断开连接 发送数据到服务器 的按钮变量
private Button btnConnect, btnDisconnect, btnSend;
// 显示接收服务器消息 按钮
private TextView Receive,receive_message;
// 输入需要发送的消息 输入框
private EditText mEdit,socketEdit;
private void initUI(){
setClickable(true);
setOrientation(VERTICAL);
LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Service.LAYOUT_INFLATER_SERVICE);
layoutInflater.inflate(R.layout.view_websocket, this, true);
// 初始化所有按钮
btnConnect = (Button) findViewById(R.id.connect);
btnDisconnect = (Button) findViewById(R.id.disconnect);
btnSend = (Button) findViewById(R.id.send);
mEdit = (EditText) findViewById(R.id.edit);
socketEdit = (EditText) findViewById(R.id.socketUrl);
receive_message = (TextView) findViewById(R.id.receive_message);
Receive = (Button) findViewById(R.id.Receive);
/**
* 创建客户端 & 服务器的连接
*/
btnConnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mConnect.isConnected()){
Toast.makeText(getContext(), "ws already connect....", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(getContext(), "ws connect....", Toast.LENGTH_SHORT).show();
try {
mConnect.connect(socketEdit.getText().toString(), new WebSocketHandler() {
@Override
public void onOpen() {
Toast.makeText(getContext(), "Status:Connect to ", Toast.LENGTH_SHORT).show();
}
@Override
public void onTextMessage(String payload) {
receive_message.setText(payload != null ? payload : "");
if(payload.equals("test")){
receive_message.setText("进入测试模式");
}
//解析json数据
JSONObject msgJson = JSON.parseObject(payload);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
msgJson.keySet().stream().forEach(k -> Log.v("cyy json key/value",k+"/"+msgJson.get(k)));
}
receive_message.setText(msgJson.getString("msg"));
}
@Override
public void onClose(int code, String reason) {
Toast.makeText(getContext(), "Connection lost..", Toast.LENGTH_SHORT).show();
}
});
} catch (WebSocketException e) {
e.printStackTrace();
}
}
});
/**
* 断开客户端 & 服务器的连接
*/
btnDisconnect.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
mConnect.disconnect();
}
});
/**
* 点击发送
*/
btnSend.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
String content = mEdit.getText().toString();
//内容为空不能发送
if (content != null && content.length() != 0) {
sendFileMessage();
}else
Toast.makeText(getContext(), "内容不能为空", Toast.LENGTH_SHORT).show();
}
});
}
//发送消息
public void sendMessage(String content) {
if (mConnect.isConnected()) {
mConnect.sendTextMessage(content);
Toast.makeText(getContext(), "发送成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getContext(), "no connection!!", Toast.LENGTH_SHORT).show();
}
}
public void sendBinaryMessage() {
if (mConnect.isConnected()) {
File imageFile = new File(Environment.getExternalStorageDirectory().
getPath() + "/Dji/com.dji.sdk.sample/photo/123.jpg");
byte[] imageBytes = new byte[0];
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
try (FileInputStream fis = new FileInputStream(imageFile)) {
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
imageBytes = bos.toByteArray();
}
} catch (IOException e) {
e.printStackTrace();
}
mConnect.sendBinaryMessage(imageBytes);
Toast.makeText(getContext(), "发送成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getContext(), "no connection!!", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onClick(View view) {
}
@Override
public int getDescription() {
return R.string.component_listview_websocket_controller;
}
@NonNull
@Override
public String getHint() {
return this.getClass().getSimpleName() + ".java";
}
/**
* 发送文件
* @param file
* @throws IOException
*/
public void sendFileMessage() {
//新建一个线程
new Thread(() -> {
File imageFile = new File(Environment.getExternalStorageDirectory().
getPath() + "/Dji/com.dji.sdk.sample/photo/123.jpg");
byte[] imageBytes = new byte[0];
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
try (FileInputStream fis = new FileInputStream(imageFile)) {
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
imageBytes = bos.toByteArray();
}
} catch (IOException e) {
e.printStackTrace();
}
Log.v("cyy okhttp","imageBytes length:"+imageBytes.length);
mConnect.sendBinaryMessage(imageBytes);
//mConnect.sendBinaryMessage(new byte[1]);
Log.v("cyy okhttp","发送成功");
}).start();
}
}
本人小白,第一次写,欢迎大佬指正。
下面就是一个需要引入的jar包