SpringBoot之集成Socket - 边见众生,边见自己 - 博客园

1、Socket是什么,这里不做介绍。开发环境:jdk1.8,win7_64旗舰版,idea

2、初始化一个springboot项目

3、开始Socket服务端实现,Socket相关接口在java.net包中已经存在,所以这里不需要再做额外的引用

    3.1、SocketServer,是Socket服务端核心

复制代码; "复制代码")

package com.geniuses.sewage_zero_straight.net.socket; import com.geniuses.sewage_zero_straight.bean.User; import com.geniuses.sewage_zero_straight.service.UserService; import com.geniuses.sewage_zero_straight.util.JSONUtil; import lombok.Data; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import static com.geniuses.sewage_zero_straight.net.socket.SocketHandler.*;

@Slf4j
@Data
@Component
@PropertySource("classpath:socket.properties")
@NoArgsConstructor public class SocketServer {

@Value("${port}") private Integer port; private boolean started; private ServerSocket serverSocket; private ExecutorService executorService = Executors.newCachedThreadPool(); public static void main(String\[\] args){ new SocketServer().start(8068);
} public void start(){
    start(null);
}
@Autowired private UserService userService;//测试使用

public void start(Integer port){
    log.info("port: {}, {}", this.port, port); try {
        serverSocket =  new ServerSocket(port == null ? this.port : port);
        started = true;
        log.info("Socket服务已启动,占用端口: {}", serverSocket.getLocalPort());
    } catch (IOException e) {
        log.error("端口冲突,异常信息:{}", e);
        System.exit(0);
    } while (started){ try {
            Socket socket = serverSocket.accept();
            socket.setKeepAlive(true);
            ClientSocket register = register(socket);
            log.info("客户端已连接,其Key值为:{}", register.getKey());
            List<User> list = userService.queryEntityListAll();
            SocketHandler.sendMessage(register, JSONUtil.toJson(list)); if (register != null){
                executorService.submit(register);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

}

复制代码; "复制代码")

    3.2、SocketPool是Socket连接的池,存放着所有已连接的socket对象,ClientSocket是自定义的一个客户端Socket类

复制代码; "复制代码")

package com.geniuses.sewage_zero_straight.net.socket; import java.util.concurrent.ConcurrentHashMap; public class SocketPool { private static final ConcurrentHashMap<String, ClientSocket> ONLINE_SOCKET_MAP = new ConcurrentHashMap<>(); public static void add(ClientSocket clientSocket){ if (clientSocket != null && !clientSocket.getKey().isEmpty())

        ONLINE\_SOCKET\_MAP.put(clientSocket.getKey(), clientSocket);
} public static void remove(String key){ if (!key.isEmpty())
        ONLINE\_SOCKET\_MAP.remove(key);
}

}

复制代码; "复制代码")

    3.3、ClientSocket

复制代码; "复制代码")

package com.geniuses.sewage_zero_straight.net.socket; import com.geniuses.sewage_zero_straight.bean.LZP_DATASERVER_TC_PROHIBSOURCE; import com.geniuses.sewage_zero_straight.service.LZP_DATASERVER_TC_PROHIBSOURCEService; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.DataInputStream; import java.io.DataOutputStream; import java.net.Socket; import java.util.concurrent.TimeUnit; import static com.geniuses.sewage_zero_straight.net.socket.SocketHandler.; /* * @author zhoujian
* 自定义封装的连接的客户端 */ @Slf4j
@Data public class ClientSocket implements Runnable{ private Socket socket; private DataInputStream inputStream; private DataOutputStream outputStream; private String key; private String message;

@Override public void run() { //每5秒进行一次客户端连接,判断是否需要释放资源
    while (true){ try {
            TimeUnit.SECONDS.sleep(5);

        } catch (InterruptedException e) {
            e.printStackTrace();
        } if (isSocketClosed(this)){
            log.info("客户端已关闭,其Key值为:{}", this.getKey()); //关闭对应的服务端资源
            close(this); break;
        }
    }
}

}

复制代码; "复制代码")

3.4、SocketHandler,Socket操作处理类

复制代码; "复制代码")

package com.geniuses.sewage_zero_straight.net.socket; import lombok.extern.slf4j.Slf4j; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import static com.geniuses.sewage_zero_straight.net.socket.SocketPool.; / * Socket操作处理类 / @Slf4j public class SocketHandler{ / * 将连接的Socket注册到Socket池中

 \* @param socket
 \* @return
 */
public static ClientSocket register(Socket socket){
    ClientSocket clientSocket = new ClientSocket();
    clientSocket.setSocket(socket); try {
        clientSocket.setInputStream(new DataInputStream(socket.getInputStream()));
        clientSocket.setOutputStream(new DataOutputStream(socket.getOutputStream())); byte\[\] bytes = new byte\[1024\];
        clientSocket.getInputStream().read(bytes);
        clientSocket.setKey(new String(bytes, "utf-8"));
        add(clientSocket); return clientSocket;
    } catch (IOException e) {
        e.printStackTrace();
    } return null;
} /** \* 向指定客户端发送信息
 \* @param clientSocket
 \* @param message */
public static void sendMessage(ClientSocket clientSocket, String message){ try {
        clientSocket.getOutputStream().write(message.getBytes("utf-8")); //clientSocket.getOutputStream().writeUTF(message);
    } catch (IOException e) {
        log.error("发送信息异常:{}", e);
        close(clientSocket);
    }
} /** \* 获取指定客户端的上传信息
 \* @param clientSocket
 \* @return
 */
public static String onMessage(ClientSocket clientSocket){ byte\[\] bytes = new byte\[1024\]; try {
        clientSocket.getInputStream().read(bytes);
        String msg = new String(bytes, "utf-8"); return msg;
    } catch (IOException e) {
        e.printStackTrace();
        close(clientSocket);
    } return null;
} /** \* 指定Socket资源回收
 \* @param clientSocket */
public static void close(ClientSocket clientSocket){
    log.info("进行资源回收"); if (clientSocket != null){
        log.info("开始回收socket相关资源,其Key为{}", clientSocket.getKey());
        remove(clientSocket.getKey());
        Socket socket = clientSocket.getSocket(); try {
            socket.shutdownInput();
            socket.shutdownOutput();
        } catch (IOException e) {
            log.error("关闭输入输出流异常,{}", e);
        }finally { try {
                socket.close();
            } catch (IOException e) {
                log.error("关闭socket异常{}", e);
            }
        }
    }
} /** \* 发送数据包,判断数据连接状态
 \* @param clientSocket
 \* @return
 */
public static boolean isSocketClosed(ClientSocket clientSocket){ try {
        clientSocket.getSocket().sendUrgentData(1); return false;
    } catch (IOException e) { return true;
    }
}

}

复制代码; "复制代码")

4、模拟客户端

复制代码; "复制代码")

package com.geniuses.sewage_zero_straight.net.socket; import lombok.extern.slf4j.Slf4j; import java.io.*; import java.net.Socket; import java.util.UUID;

@Slf4j public class ChatClient { public static void main(String[] args) throws IOException {

    String host = "192.168.2.156"; int port = 8068; //与服务端建立连接
    Socket socket = new Socket(host, port);
    socket.setOOBInline(true); //建立连接后获取输出流
    DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
    DataInputStream inputStream = new DataInputStream(socket.getInputStream());
    String uuid = UUID.randomUUID().toString();
    log.info("uuid: {}", uuid);
    outputStream.write(uuid.getBytes()); DataInputStream inputStream1 = new DataInputStream(socket.getInputStream());
    String content = ""; while (true){ byte\[\] buff = new byte\[1024\];
        inputStream.read(buff);
        String buffer = new String(buff, "utf-8");
        content += buffer;
        log.info("info: {}", buff);
        File file = new File("json.json");
        FileWriter fileWriter = new FileWriter(file);
        fileWriter.write(content);
        fileWriter.flush();
    }
}

}

复制代码; "复制代码")

5、Socket配置,这样,在启动SpringBoot应用的时候,就会将Socket服务也一并启动(此处有坑,也就是启动方式的问题,使用内置的tomcat启动是可以这样操作的,如果打包为war包在外置的tomcat进行启动,那么这里的设置是无效的,如何操作:)

复制代码; "复制代码")

package com.geniuses.sewage_zero_straight; import com.geniuses.sewage_zero_straight.net.socket.SocketServer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext;

@SpringBootApplication public class SocketApplication{ public static void main(String[] args) {

    ApplicationContext applicationContext = SpringApplication.run(SocketApplication.class, args);
    applicationContext.getBean(SocketServer.class).start();//在spring容器启动后,取到已经初始化的SocketServer,启动Socket服务

}

}

复制代码; "复制代码")

6、这里只是简单的Socket实现,更多...

作者:thread_zhou

出处:https://www.cnblogs.com/threadj/p/10553048.html

本站使用「署名 4.0 国际」创作共享协议,转载请在文章明显位置注明作者及出处。

分类: socket, Spring Boot

标签: spring boot, socket

好文要顶;) 关注我;) 收藏该文;) ; "分享至新浪微博") ; "分享至微信")

边见众生,边见自己
关注 - 21
粉丝 - 4

+加关注;)

« 上一篇: SpringBoot之集成WebSocket
» 下一篇: SpringBoot集成Socket服务后打包(war包)启动时如何启动Socket服务(web应用外部tomcat启动)


Original url: Access
Created at: 2020-01-14 12:02:31
Category: default
Tags: none

请先后发表评论
  • 最新评论
  • 总共0条评论