Java Socket基础
较基础的Java Socket通信样例!
一、长连接通信
客户端和服务端建立通道后,Socket一直开着。两端通过read()等待消息。
1)简易聊天
服务端可主动对各个客户端发送消息,而各客户端只能单独发送给服务端。当然,只要你愿意,在服务端改下,即可转发了。
附件解压工程ChatSocket,运行TestServer、TestClient即可。src下还有两批处理,详细看TestServer文件内注释了。
1.1)ChatServer.java
- /**
- * 长连接、1对n主动发消息的服务器
- *
- * @author Join
- */
- public class ChatServer extends Thread {
- /** 服务端口 */
- private int port;
- /** 服务套接字 */
- private ServerSocket mServerSocket;
- /** 线程池 */
- private ExecutorService pool;
- /** 客户端套接字集合 */
- private ArrayList<Socket> mClientList;
- public ChatServer(int port) {
- this.port = port;
- pool = Executors.newCachedThreadPool(); // 缓存线程池
- mClientList = new ArrayList<Socket>();
- }
- @Override
- public void run() {
- try {
- mServerSocket = new ServerSocket(port); // 创建本地特定端口服务器套接字
- Socket client = null;
- while (true) {
- client = mServerSocket.accept(); // 接收连接的套接字
- mClientList.add(client); // 加入客户端列表
- System.out.println(client.getInetAddress() + "建立了连接");
- pool.execute(new ThreadServer(client)); // 新线程执行任务
- }
- } catch (BindException e) { // 端口使用中
- System.out.println("端口使用中,请关闭后重开!");
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- /** 各个连接客户端的服务线程 */
- private class ThreadServer extends Thread {
- private Socket client;
- public ThreadServer(Socket client) {
- this.client = client;
- }
- @Override
- public void run() {
- DataInputStream in = null;
- DataOutputStream out = null;
- try {
- in = new DataInputStream(client.getInputStream());
- out = new DataOutputStream(client.getOutputStream());
- BufferedReader wt = new BufferedReader(new InputStreamReader(
- System.in)); // 控制台输入流
- while (true) {
- if (in.available() > 0) {
- /* 有数据时接收 */
- String str = in.readUTF();
- System.out.println(str);
- /* 接收end或空时,退出 */
- if (null == str || "end".equals(str)) {
- System.out
- .println(client.getInetAddress() + "正常退出");
- break;
- }
- /* 回复或转发已接收数据 */
- } else {
- if (wt.ready()) {
- /* 控制台有数据时发送 */
- String str = wt.readLine();
- sendMessage(str); // 群发消息
- } else {
- try {
- /* 发送紧急数据,判断连接 */
- client.sendUrgentData(0xFF);
- Thread.sleep(100);
- } catch (Exception e) {
- System.out.println(client.getInetAddress()
- + "断开连接");
- break;
- }
- }
- }
- }
- } catch (SocketException e) { // Connection reset
- System.out.println(client.getInetAddress() + "异常退出");
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- mClientList.remove(client); // 移除当前客户端
- try {
- if (null != in) {
- in.close();
- }
- if (null != out) {
- out.close();
- }
- if (null != client) {
- client.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- /**
- * 群发信息
- * @throws IOException
- */
- public void sendMessage(String msg) throws IOException {
- DataOutputStream out = null;
- for (Socket client : mClientList) {
- out = new DataOutputStream(client.getOutputStream());
- out.writeUTF(msg);
- out.flush();
- }
- }
- }
1.2)ChatClient.java
- /**
- * 接收和发送消息的客户端
- *
- * @author Join
- */
- public class ChatClient extends Thread {
- /** 套接字地址 */
- private SocketAddress address;
- /** 超时时间 */
- private int timeout;
- public ChatClient(String host, int port, int timeout) {
- this.address = new InetSocketAddress(host, port);
- this.timeout = timeout;
- }
- @Override
- public void run() {
- Socket socket = new Socket(); // 创建未连接套接字
- try {
- // socket.setOOBInline(false); // 默认即是false,表示不处理紧急数据
- socket.connect(address, timeout); // 连接到服务器,并指定超时时间
- handleSocket(socket); // 数据接收发送处理
- } catch (ConnectException e) { // 拒绝连接
- System.out.println("连接不上服务器");
- } catch (SocketTimeoutException e) { // 连接超时
- System.out.println("连接服务器超时");
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- if (null != socket) {
- socket.close(); // 关闭Socket
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- private void handleSocket(Socket socket) {
- DataInputStream in = null;
- DataOutputStream out = null;
- try {
- in = new DataInputStream(socket.getInputStream());
- out = new DataOutputStream(socket.getOutputStream());
- BufferedReader wt = new BufferedReader(new InputStreamReader(
- System.in)); // 控制台输入流
- while (true) {
- if (wt.ready()) {
- /* 控制台有数据时发送 */
- String str = wt.readLine();
- out.writeUTF(str);
- out.flush();
- /* 发送end时,自身也退出 */
- if (str.equals("end")) {
- break;
- }
- } else {
- try {
- /* 发送紧急数据,判断连接 */
- socket.sendUrgentData(0xFF);
- Thread.sleep(100);
- } catch (Exception e) {
- System.out.println("服务器断开连接");
- break;
- }
- }
- /* 有数据时接收并输出 */
- if (in.available() > 0)
- System.out.println(in.readUTF());
- }
- } catch (SocketException e) { // Connection reset
- System.out.println("服务器异常");
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- if (null != in) {
- in.close();
- }
- if (null != out) {
- out.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
本文转自winorlose2000 51CTO博客,原文链接:http://blog.51cto.com/vaero/893837,如需转载请自行联系原作者