00023.09 TCP协议编程:多次通信、多个客户端同时发送 单词反转(多线程)

TCP协议编程目录

前言

接上一篇文章

一、解决上一篇的问题,多次通信怎么处理

需求,假如客户端发一个词语给服务端,服务端给它反转,发回来,就可以进行多次通信,又来有回

(1)服务端

在这里插入图片描述
在这里插入图片描述
InputStream:得到的是字节输入流,InputStream.read(“filename”)之后,得到字节流

Reader:读取的是字符流
InputStreamReader:从字节到字符的桥梁

InputStreamReader(InputStream.read(“filename”));

reader.read(InputStreamReader(InputStream in));便可从字节变为字符,打印显示了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
服务器端完成了,下面客户端怎么做呢?

(2)客户端

在这里插入图片描述
在这里插入图片描述
注意
(1)next和nextLine
next是表示下一个值;
nextLine是表示:下一行值;
这个要你一次输入多个数值才能看出区别
(2)readLine()和read()
readLine()是调用了read(char[] cbuf, int off, int len) 来读取数据,后面再根据”/r”或”/n”来进行数据处理
read 返回的是 int;readLine 返回的是String
读入的数据要注意有/r或/n或/r/n
使用socket之类的数据流时,要注意看是否需要避免使用readLine(),以免为了等待一个换行/回车符而一直阻塞
在这里插入图片描述
在这里插入图片描述
如果想要同时多个客户端连接怎么办?

二、多个客户端同时发送单词反转.

需求:要求能够多个客户端能够同时发送单词反转
先想一个问题,这个需求需不需要改客户端的代码?
答案是不需要,因为客户端的操作跟之前是一模一样的,就是发送词语,然后接收返回的数据
服务端要改,那么怎么改呢?
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
遇到的问题,在这里插入图片描述
这个Socke报错了,Socket怎么传过来?
在这里插入图片描述
解决办法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这样用构造器,在创建对象的时候就传过来了
在这里插入图片描述
在这里插入图片描述
这个方法是父类里面的 ,即 是 Thread 里面的
父类的方法没有抛出异常子类能抛出异常吗,不能,所以只能选择try-catch

在这里插入图片描述
完整代码:
服务端:

package com.atguigu.test13;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * 服务器端:
 * 	(1)接收客户端的连接
 *  (2)接收客户端的词语
 *  (3)把词语“反转”返回给客户端
 *  (2)(3)多次,直到客户端发送"bye"为止
 *  
 *  加一个条件,服务器端可以同时接收n个客户端连接
 *  服务器端得加多线程
 */
public class TestServer {
	public static void main(String[] args) throws IOException {
		//1、开启服务器
		ServerSocket server = new ServerSocket(8989);
		
		boolean flag = true;
		while(flag){
			//2、接收一个客户端的连接
			Socket socket = server.accept();//每个客户端的socket是独立的
			
			//为没一个客户端开启一个独立的线程维护它的通信
			MessageHandler mh = new MessageHandler(socket);
			mh.start();
		}
			
		//5、关闭服务器
		server.close();
	}
}
class MessageHandler extends Thread{
	private Socket socket;
	
	public MessageHandler(Socket socket) {
		super();
		this.socket = socket;
	}

	public void run(){
		try {
			//3、先获取输入流和输出流
			InputStream in = socket.getInputStream();
			/*
			 * 因为是接收一个词语,反转一个,返回一个
			 * 那么如果仅仅使用字节流,不好区分词语
			 * 需要用到字符流
			 * 那么就意味着需要把字节流转为字符流
			 */
			InputStreamReader isr = new InputStreamReader(in);//这里不涉及编码问题,仅仅为了转换流的类型
			/*
			 * 字符流中几个字符是一个词语
			 * 那么我们这里选择“换行符”来作为词语的分割
			 * 意味着我们可以按行读取Scanner或BufferedReader
			 */
			BufferedReader br = new BufferedReader(isr);
			
			OutputStream out = socket.getOutputStream();
			/*
			 * 客户端收到字节,同样不方便处理几个字节是一个词语,仍然要把字节输出流转为字符流
			 * 而且字符之间也不好区分,那么也选择“换行符”进行区别词语
			 * 我们现在需要把OutputStream转为一个可以按行写的字符流或其他的处理流
			 * 
			 * 可以按行写的:BufferedWriter(newLine())
			 * 		   PrintStream(println())
			 */
			PrintStream ps = new PrintStream(out);
			
			//从客户端接收词语
			String word;
			while((word = br.readLine()) != null){
				if("bye".equals(word)){
					break;
				}
				
				//如果不是bye,要反转,并且返回
				StringBuilder sb = new StringBuilder(word);
				sb.reverse();
				
				//返回给客户端
				ps.println(sb.toString());
			}
			
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				//4、断开
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

客户端:

package com.atguigu.test13;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

/*
 * 客户端:
 * (1)从键盘输入词语
 * (2)发送给服务器
 * (3)接收服务器返回的结果
 * (1)(2)(3)多次进行,直到键盘输入bye并发送给发服务器之后就结束
 * 
 * 加一个条件,服务器端可以同时接收n个客户端连接
 * 客户端代码不用修改
 */
public class TestClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
		//1、连接服务器
		Socket socket = new Socket("192.168.30.142",8989);
		
		/*
		 *  * (1)从键盘输入词语
		 * (2)发送给服务器
		 * (3)接收服务器返回的结果
		 * (1)(2)(3)多次进行,直到键盘输入bye并发送给发服务器之后就结束
		 */
		Scanner input = new Scanner(System.in);
		/*
		 * 同样考虑到发送词语,以及词语之间分割问题,那我们选择PrintStream和BufferedReader
		 */
		PrintStream ps = new PrintStream(socket.getOutputStream());
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		while(true){
			//从键盘输入词语
			System.out.print("请输入词语:");
			String word = input.next();
			
			//发送给服务器端
			ps.println(word);
			
			if("bye".equals(word)){
				break;
			}
			
			//接收服务器返回的结果
			String result = br.readLine();
			System.out.println("服务器返回的反转后的结果:" + result);
		}
		
		input.close();
		socket.close();
	}
}

注意

InputStream:得到的是字节输入流,InputStream.read(“filename”)之后,得到字节流

Reader:读取的是字符流
InputStreamReader:从字节到字符的桥梁

InputStreamReader(InputStream.read(“filename”));

reader.read(InputStreamReader(InputStream in));便可从字节变为字符,打印显示了

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值