java.net.Socket 代表两台机器之间网络连接的对象
客户端必须要认识服务器,服务器必须要认识所有的客户端。
- 如何建立客户端与服务器之间的初始连接
- 如何传送信息到服务器
- 如何接收来自服务器的信息
要创建Socket连接,必须知道服务器在哪里以及用哪个端口来收发数据,也就是IP地址和端口号
try { Socket socket = new Socket("192.168.20.135", 5000); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
常用端口
- 80 # HTTP网页服务器,HTTPS使用443端口,FTP使用20端口
- 110 # POP3邮件服务器
- 25 # SMTP邮局交换服务器
- 23 # Telnet服务器
0~1023端口保留给已知的特定服务使用,可以从1024~65535之间挑选。
数据读写BufferedReader
使用 BufferedReader 从 Socket 上读取数据
Socket socket = new Socket("192.168.20.135", 5000); InputStreamReader stream = new InputStreamReader(socket.getInputStream()); //从 Socket 上取得输入串流 BufferedReader reader = new BufferedReader(stream); String msg = reader.readLine(); reader.close();
PrintWriter
用 PrintWriter 写数据到 Socket 上
Socket socket = new Socket("192.168.20.135", 5000); PrintWriter writer = new PrintWriter(socket.getOutputStream()); //连接 Socket 和 String 流 writer.println("message to send"); //带换行 writer.print("another message"); writer.close();Socket Server
一对Socket,一个用于等待用户请求的ServerSocket,一个用于与用户通信的Socket
ServerSocket
try { ServerSocket serverSocket = new ServerSocket(4242); while(true){ //服务器进入无穷循环等待客户端的请求 Socket socket = serverSocket.accept(); //此方法会停下来等待要求到达之后再继续 PrintWriter writer = new PrintWriter(socket.getOutputStream()); writer.println("Welcome..."); writer.close(); } } catch (IOException e) { e.printStackTrace(); }工作方式
1 服务器应用程序对特定端口创建出ServerSocket
ServerSocket serverSocket = new ServerSocket(4242);
这会让服务器应用程序开始监听来自 4242 端口的客户端请求
2 客户端对服务器应用程序建立Socket连接
Socket socket = new Socket("192.168.20.135", 9000);
客户端根据服务器的IP地址和端口号建立连接
3 服务器创建出与客户端通信的新的Socket
Socket socket = serverSocket.accept();
accept() 方法会在等待用户的Socket连接时闲置着,当用户连上来时,此方法会返回一个不同端口上的新的Socket以便与客户端通信。如此ServerSocket可以空出来等待其他的用户。
取得所有连线ListclientOutputStreams = new ArrayList<>(); //定义客户端输出流列表
try { ServerSocket serverSocket = new ServerSocket(9000); //监听连接到9000端口的所有客户端 while(true){ Socket clientSocket = serverSocket.accept(); PrintWriter writer = new PrintWriter(clientSocket.getOutputStream()); //取得客户端输出流 clientOutputStreams.add(writer); //添加到输出流列表 //启动监听客户端输入流线程 Thread readClientMsg = new Thread(new ClientHandler(clientSocket)); readClientMsg.start(); } } catch (IOException e) { e.printStackTrace(); }群发消息
public void sendToAll(String msg){ Iterator取得客户端消息itClient = clientOutputStreams.iterator(); //利用迭代器进行遍历 while(itClient.hasNext()){ PrintWriter writer = itClient.next(); writer.println(msg); writer.flush(); } }
利用多线程循环监听客户端发来的消息,如果获取到消息就发送给所有用户
线程在取得客户端连接时就启动
Socket clientSocket = serverSocket.accept(); Thread readClientMsg = new Thread(new ClientHandler(clientSocket)); readClientMsg.start();
class ClientHandler implements Runnable{ BufferedReader reader; Socket socket; public ClientHandler(Socket clientSocket){ //绑定客户端并取得输入流 this.socket = clientSocket; try { InputStreamReader is = new InputStreamReader(socket.getInputStream()); reader = new BufferedReader(is); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { String msg; //循环监听输入流,取到消息后发送给所有客户端 try { while((msg = reader.readLine()) != null){ sendToAll(msg); } } catch (IOException e) { e.printStackTrace(); } } }Socket Client 发送消息给服务器
Socket socket; PrintWriter writer; private void setSocket(){ try { socket = new Socket("192.168.20.135", 4242); writer = new PrintWriter(socket.getOutputStream()); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private void sendMsg(String msg){ writer.println(msg); writer.flush(); }接收服务器消息
结合以上发送消息合并代码
BufferedReader reader; private void setSocket(){ try { socket = new Socket("192.168.20.135", 4242); writer = new PrintWriter(socket.getOutputStream()); //定义输出流,通过发送按钮发送消息给服务器 InputStreamReader streamReader = new InputStreamReader(socket.getInputStream()); //定义输入流 reader = new BufferedReader(streamReader); //绑定到缓存输入流,利用多线程循环循环查询服务器消息并接收 } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
开启新线程循环接收服务器消息
Thread readMsg = new Thread(new ReadMsg()); readMsg.start();
private class ReadMsg implements Runnable{ @Override public void run() { String msg; try { while((msg = reader.readLine()) != null){ //获取到服务器信息 System.out.println(msg); } } catch (IOException e) { e.printStackTrace(); } } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)