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

本文详细介绍了一种基于Java的全双工通信模型实现,包括服务器端和客户端的设计。服务器端与客户端各采用一个线程专门发送消息,一个线程专门接收消息,实现了双向同时通信。文章深入分析了代码结构,如使用BufferedReader和PrintWriter进行输入输出流操作,以及ServerSocket和Socket的连接机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码分析

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

执行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值