【橘猫笔记】TCP网络编程 ServerSocket和Socket实现全双工通信

代码分析

服务器端:一个线程专门发送消息,一个线程专门接收消息
客户端:一个线程专门发送消息,一个线程专门接收消息
服务器端和客户端全双工通信模型,服务器端先运行,否则客户端会因为无法连接服务器端而产生错误。服务器一直在监听。然后客户端开始运行,并且请求连接服务器。
详细分析
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();
				}
			}
		}
	}
}

执行结果

【橘猫笔记】TCP网络编程 ServerSocket和Socket实现全双工通信_第1张图片

你可能感兴趣的:(【橘猫笔记】TCP网络编程 ServerSocket和Socket实现全双工通信)