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