代码分析
服务器端:一个线程专门发送消息,一个线程专门接收消息
客户端:一个线程专门发送消息,一个线程专门接收消息
服务器端和客户端全双工通信模型,服务器端先运行,否则客户端会因为无法连接服务器端而产生错误。服务器一直在监听。然后客户端开始运行,并且请求连接服务器。
详细分析:
Server
类里面的主线程里面实现的是socket
监听,定义了一个端口Port:9999
还实现了循环读取套接字的输出流,即使用了BufferedReader
,子线程SendImg
用于发送信息,使用了PrintWriter
注意:
使用BufferedReader
字符流读一行,readLine()
方法是阻塞的,直到程序遇到了换行符或者是对应流的结束符readLine()
方法才会认为读到了一行,才会结束其阻塞,让程序继续往下执行。
Server
端的accept()
也是阻塞的,只有侦听到客户端的握手请求,完成连接后,程序才会继续运行。
Server客户端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/*
服务器端:一个线程专门发送消息,一个线程专门接收消息。
主线程专门接收,子线程一直在线准备发送(因为程序执行的先后顺序)
---该例子演示的是全双工通信---
客户端:一个线程专门发送消息,一个线程专门接收消息。
*/
public class Server {
// 主线程负责接收服务器发来的信息
public static void main(String[] args) throws IOException {
// 创建服务端对象
ServerSocket ss = new ServerSocket(9999);
System.out.println("等待客户端连接");
// 侦听并接受到此套接字的连接。
Socket s = ss.accept();
System.out.println("连接成功");
SendImg send = new SendImg(s);
send.start();
// 创建读取字符流
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
while (true) {
// 读取客户端发过来的信息
String clientimg = br.readLine();
System.out.println("客户端说:" + clientimg+"端口:"+s.getPort());
if(clientimg.equals("end")){
System.out.println("通信结束");
System.exit(0);
}
}
}
}
//send线程负责发出的信息
class SendImg extends Thread {
Socket ss;
PrintWriter pw;
Scanner sc = new Scanner(System.in);
public SendImg(Socket s) {
this.ss = s;
try {
this.pw = new PrintWriter(s.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
while (true) {
// 服务端发送信息
String in = sc.next();
pw.println(in);
pw.flush();// 输出流刷新
if (in.equals("end")) {
break;
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (pw != null) {
pw.close();
}
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
客户端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException{
// 创建客户端对象
Socket s = new Socket("192.168.0.243", 9999);
SendImgClient sendclient = new SendImgClient(s);
sendclient.start();
// 创建读取字符流
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
while(true){
//读取服务端发过来的信息
String serverimg = br.readLine();
System.out.println("服务端说:"+serverimg);
if(serverimg.equals("end")){
System.out.println("通信结束");
System.exit(0);
}
}
}
}
class SendImgClient extends Thread {
Socket ss;
PrintWriter pw;
Scanner sc =new Scanner(System.in);
public SendImgClient(Socket s) {
this.ss = s;
try {
this.pw = new PrintWriter(s.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
while (true) {
// 客户端发送信息
String in = sc.next();
pw.println(in);
pw.flush();// 输出流刷新
if (in.equals("end")) {
break;
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (pw != null) {
pw.close();
}
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}