Socket(套接字)
使用Socket编程实现数据的交互需要经历以下几个步骤:
1、创建Socket:
Socket socket = new Socket("host",port);
2、打开IO流
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);//输出流
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))//输入流
注: socket属于服务器,那么socket的方法getOutputStream就是向客户端输出数据,getInputStream获取客户端传过来的数据
3、进行数据的交互
out.print() in.read();
4、关闭Socket
socket.close();
服务端跟客户端有所不同,客户端只要创建socket并且请求服务器连接connect,服务器创建完socket使用ServerSocket.accept()方法
阻塞程序直到收到了来自客户端的请求,接收到来自客户端的socket继续往下执行。
其中客户端代码如下:
import java.net.*; import java.io.*; public class Client { boolean flag = false;//当遇到客户端输入bye取消与服务端连接的标识 public Client(){ try{ Socket socket =new Socket("127.0.0.1",4800);//(host,port) System.out.println("客户端已经开启----"); new Thread(new Output(socket)).start(); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));//获取来自服务端的信息 String str = in.readLine();//读取信息 while(!str.equals("bye")) { System.out.println("服务端:"+str); str = in.readLine();//当in每次调用readLine方法就会往下读取一行,慎用 } in.close(); if (flag==true){ socket.close(); } } catch(Exception e){ e.printStackTrace(); } } //当客户端没有写入信息的时候需要写一个线程来实现写操作,不然程序就会被卡在readLine一直获取键盘信息 class Output implements Runnable{ Socket socket; public Output(Socket socket){ this.socket = socket; } public void run(){ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); try { PrintWriter out = new PrintWriter(socket.getOutputStream(),true); String str = br.readLine(); while(!str.equals("bye")) { System.out.println("客户端:"+str); out.print(str+"\n");//从键盘没有获取到回车按键,需要加\n判断一次输入为一行 out.flush(); str = br.readLine(); if (str.equals("bye")) { flag = true; } } br.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { new Client(); } }
服务端代码如下:
import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class Server { boolean flag = false; public Server(){ try { ServerSocket serverSocket = new ServerSocket(4800); System.out.println("服务端正在等待客户端请求......"); Socket socket = serverSocket.accept();//一直等待客户端的请求 System.out.println("connect success"); new Thread(new Output(socket)).start(); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); /* int i = 0; while ((i = in.read()) != 0){ System.out.println(i); }*/ String str = in.readLine(); while(!str.equals("bye")) { System.out.println("客户端:" + str); str = in.readLine(); } in.close(); if (flag==true) { socket.close(); serverSocket.close(); } } catch (IOException e) { e.printStackTrace(); } } class Output implements Runnable{ Socket socket; public Output(Socket socket){ this.socket = socket; } public void run(){ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); try { PrintWriter out = new PrintWriter(socket.getOutputStream(),true); String str = br.readLine(); while(!str.equals("bye")) { System.out.println("服务端:"+str); out.print(str+"\n"); out.flush(); str = br.readLine(); if (str.equals("bye")) { flag = true; } } br.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { new Server(); } }
总结
今天使用socket来实现客户端与服务端的通信功能,遇到了很多问题,其中一个比较严重的就是没有将写操作放入线程中进行,导致程序没有输出信息,第二个问题是当获取到从客户端/服务端来的信息时候,我是一行行的进行读取,但是没有读取到回车按键,无法区分一行的信息,导致客户端输入的信息,服务端无法接收,在朋友的debug下,使用了以下这个方法调试是否有数据传到另一边:
int i = 0; while ((i = in.read()) != 0){ System.out.println(i);
使用BufferReader的read方法返回的ASCII码,强转为int 可以直接获取原来的值(在ASCII范围内的值)。