java客户端与服务端建立连接 线程 ServerSocket
2017-06-25 09:19
495 查看
package chat; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner; /* * 聊天客户端 */ public class Client { /* * java.net.Scoket 套接字 * 封装了TCP通讯,使用它可以通过网络连接到服务端并进行数据交换(通讯) */ private Socket socket; /* * 构造方法 * 用于初始化客户端 */ public Client() throws Exception{ try { /* * 实例化Scoket的过程就是与远端计算机建立连接的过程 * 实际上建立连接是客户端应用程序与服务端应用程序建立的连接 * 那么这里实例化Scoket需要传入两个参数 * 1:服务器端计算机的IP地址(用于在网络中找到服务器端电脑) * 2:端口号(通过端口号可以找到运行在服务器中的服务端应用程序) */ System.out.println("正在连接服务器。。。"); socket = new Socket("localhost",8080); System.out.println("已建立连接!"); } catch (Exception e) { throw e; } } /* * 客户端的启动方法 */ public void start(){ try { /* * Socket 提供方法: * OutputStream getOutputStream * 该方法可以获取一个字节输出流,通过该流写出的数据都会发送给远端计算机 * 对于客户而言,远端就是服务端 */ Scanner scan = new Scanner(System.in); //客户端输出 OutputStream out = socket.getOutputStream(); //转换指定字符集 OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8"); //缓冲 字符输出流 PrintWriter pw = new PrintWriter(osw,true); //启动读取服务端发送过来消息的线程 ServerHandler handler = new ServerHandler(); Thread t = new Thread(handler); t.start(); System.out.println("开始聊天"); String message = null; while(true){ message = scan.nextLine(); pw.println(message); // //读取服务端发送回来的内容 // message = br.readLine() ; // System.out.println(message); } } catch (Exception e) { e.printStackTrace(); } } /* * 该线程专门用来接收服务端发送过来的消息并输出到控制台 */ private class ServerHandler implements Runnable{ public void run(){ try { //客户端输入 InputStream in = socket.getInputStream(); //字符 InputStreamReader isr = new InputStreamReader(in,"utf-8"); //字符 BufferedReader br = new BufferedReader(isr); String message = null; while((message = br.readLine())!= null){ System.out.println(message); } } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) { try { Client client = new Client(); client.start(); } catch (Exception e) { e.printStackTrace(); } } }
package chat; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; /* * 服务器端 * */ public class Server { /* * java.net.ServerSocket; 运行在服务端的ServerScoket主要职责: * 1:向OS申请服务端口(客户端就是同过这个端口与服务端建立连接的) * 2:监听服务端口并建立与客户端的连接 */ private ServerSocket server; //存放所有客户端的输出流,用于广播消息 private List<PrintWriter> allOut; /* * 服务端构造方法,用来初始化服务端 */ public Server() throws Exception { try { /* * 初始化ServerSocket的同时向系统申请服务器端口, 若该端口已经被其他程序占用则会抛出异常 */ server = new ServerSocket(8080); allOut = new ArrayList<PrintWriter>(); } catch (Exception e) { // 将来在这里可以记录日志 // 异常若不应当在这里处理,继续抛出 throw e; } } /* * 服务端开始工作的方法 */ public void start() { try { /* * ServerSocket提供方法: Socket accept() * 该方法是一个阻塞方法,作用是监听服务端口,等待客户端的连接一旦一个客户端请求连接 * 那么accept方法会解除阻塞,并返回一个Socket实例,服务器就可以通过这个Socket * 实例与客户端交互 */ while(true){ System.out.println("等待一个客户端连接。。"); Socket socket = server.accept(); System.out.println("一个客户端连接了"); //启动一个线程来负责与该客户端交互 ClientHandler handler = new ClientHandler(socket); Thread t = new Thread(handler); t.start(); } } catch (Exception e) { e.printStackTrace(); } } private class ClientHandler implements Runnable { /* * 当前线程就是通过这个Socket与指定客户端交互的 * */ private Socket socket; //当前客户端的地址信息 private String host; public ClientHandler(Socket socket) { this.socket = socket; //获取该客户端地址信息(远端计算机地址信息) InetAddress address = socket.getInetAddress(); host = address.getHostAddress(); } public void run() { PrintWriter pw = null; try { /* * Socket 提供方法: InputStream getInputStream() * 通过这个流读取到的数据就是远端发送过来的数据 */ // 服务端输入 // 字节 InputStream in = socket.getInputStream(); // 字符 InputStreamReader isr = new InputStreamReader(in, "utf-8"); // 字符 BufferedReader br = new BufferedReader(isr); // 服务端输出 OutputStream out = socket.getOutputStream(); // 转换指定字符集 OutputStreamWriter osw = new OutputStreamWriter(out, "UTF-8"); // 缓冲 字符输出流 pw = new PrintWriter(osw, true); //将该客户端的输出流存入共享集合 synchronized(allOut){//锁集合 保证多个线程不能同时调用 allOut.add(pw); } //广播当前客户端上线 sendMessage(host+"上线了"); String message = null; while ((message = br.readLine()) != null) { Thread t = Thread.currentThread(); System.out.println("客户" +t.getName()+":"+ message); // // 发送回给客户端 // pw.println("客户端说:" + message); //遍历集合,发送给所有客户端 sendMessage(host+":"+message); } } catch (Exception e) { //e.printStackTrace(); }finally{ //处理客户端断开连接后的操作 //将该客户端的输出流从共享集合中删除 synchronized(allOut){ allOut.remove(pw); } sendMessage(host+"下线了"); try{ /* * 网络通讯完毕后关闭socket */ socket.close(); }catch(Exception e){ } } } /* * 将消息广播给所有客户端 */ private void sendMessage(String message){ synchronized(allOut){ for(PrintWriter o : allOut){ o.println(message); } } } } public static void main(String[] args) { try { Server server = new Server(); server.start(); } catch (Exception e) { e.printStackTrace(); } } }
相关文章推荐
- java Socket 多个客户端连接同一个服务端
- java基础入门-建立可以多客户端链接的ServerSocket
- java基础入门-建立可以多客户端链接的ServerSocket
- 基于Socket的TCP长连接(服务端Java+客户端Android),Service配合AIDL实现
- java基础入门-建立可以多客户端链接的ServerSocket
- java服务端客户端交互系列(一)socket连接
- java实现socket客户端连接服务端
- Java Socket实现多个客户端连接同一个服务端
- SOCKET客户端与服务端长时间通信后,会连接不上服务端的问题,以及server端UDP丢包的问题
- 网络 客户端 多种方法 建立与服务端的连接 接口:服务器名,IP socket connect
- android mina客户端连接抛java.net.SocketException: Tra...
- Java Socket多线程服务端、客户端
- Java ServerSocket的服务端代码介绍
- socket ( java ) 简单多个客户端、服务端通信(多线程)
- Java线程的传说(3)——如何关闭一个正在accept的ServerSocket?
- 简单的socket连接,实现服务端可以获得多个客户端连接(备份,方便以后查询)
- 多线程多端口Socket服务端客户端代码 java
- Socket通讯(objetive-c)客户端与(JAVA)服务端的特殊点
- 使用Java与Flex建立Socket连接(已解决沙箱问题)
- 客户端分段读取服务端的socket信息 客户端连接多台socket服务端