0
点赞
收藏
分享

微信扫一扫

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


TCP协议编程目录

文章目录

  • ​​TCP协议编程目录​​
  • ​​前言​​
  • ​​一、解决上一篇的问题,多次通信怎么处理​​
  • ​​(1)服务端​​
  • ​​(2)客户端​​
  • ​​二、多个客户端同时发送单词反转.​​
  • ​​注意​​

前言

接上一篇文章

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

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

(1)服务端

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


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


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

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

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

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

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


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


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


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


服务器端完成了,下面客户端怎么做呢?

(2)客户端

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


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


注意

(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(),以免为了等待一个换行/回车符而一直阻塞

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


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


如果想要同时多个客户端连接怎么办?

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

需求:要求能够多个客户端能够同时发送单词反转

先想一个问题,这个需求需不需要改客户端的代码?

答案是不需要,因为客户端的操作跟之前是一模一样的,就是发送词语,然后接收返回的数据

服务端要改,那么怎么改呢?

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

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


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


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


遇到的问题,

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


这个Socke报错了,Socket怎么传过来?

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


解决办法

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


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


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


这样用构造器,在创建对象的时候就传过来了

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


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


这个方法是父类里面的 ,即 是 Thread 里面的

父类的方法没有抛出异常子类能抛出异常吗,不能,所以只能选择try-catch

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


完整代码:

服务端:

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));便可从字节变为字符,打印显示了


举报

相关推荐

0 条评论