在网络编程中,主要的是ServerSocket和Socket这两个类,以及输入输出流的包装。
需要注意的是,会进行阻塞的几个点。accept()方法、readLine()方法以及键盘输入等都会进行阻塞。
在服务端,使用新起线程来和客户端连接,保证每个客户端都是一个新的线程!这样,就算发生阻塞时,也只会阻塞一个线程,其他线程仍旧可以正常工作。
客户端与服务端通过包装后的输入输出流来进行信息交互,服务端的写就是客户端的读,客户端的写就是服务端的读。
服务端代码如下:
public class MyServer {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(7878);
while(true) {
Socket s = ss.accept();//阻塞,等待客户端连接
System.out.println("获得一个客户端连接:" + s.getInetAddress().getHostAddress());
new Handler(s).start();
//new Handler(s).run();
//新的客户端无法获取socket,readLine方法会阻塞,当前循环不能开启下一次循环
}
}
private static class Handler extends Thread{
Socket socket = null;
public Handler(Socket s) {
this.socket = s;
}
@Override
public void run() {
try {
BufferedReader read = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
PrintWriter write = new PrintWriter(
socket.getOutputStream());
String msg = null;
//readLine()方法会进行阻塞
//将读取到的客户端输入的信息赋值给msg
while((msg = read.readLine())!=null) {
System.out.println("client:" + msg);
//向客户端写信息
write.println("server:" + msg);
write.flush();
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
客户端代码如下:
public class MyClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1", 7878);
BufferedReader read = null;
PrintWriter write = null;
Scanner scan = new Scanner(System.in);
String msg = null;
if(socket.isConnected()) {
System.out.println("连接服务器成功");
read = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
write = new PrintWriter(socket.getOutputStream());
}
while(true) {
//阻塞,等待输入
msg = scan.nextLine();
//向服务端写入数据
write.println(msg);
write.flush();
msg = read.readLine();
System.out.println(msg);
}
}
}