本代码演示了使用缓冲区技术接收键盘输入时的问题,并做了相应的处理。
/*
需求:建立一个文本转换服务器
客户端给服务端发送文本,服务端会将文件转换成大写在返回给客户端。
客户端可以不断的进行文本转换,当客户端输入 over 时,转换结束。
分析:
客户端:既然是操作设备上的数据,那么就可以使用io技术,并按照Io的
操作规律来思考.
源:键盘录入
目的:网络设备,网络输出流
而且操作的是文本数据,可以选择字符流。
步骤:
1:
*/
import java.io.*;
import java.net.*;
/*
注意这儿使用的是 缓冲流所以写完后如果不刷新,则数据在缓冲区中。
下面代码的问题:
现象:客户端和服务端都在莫名的等待。
为什么呢?
因为客户端和服务端都有阻塞式方法,这些方法没有读到结束标记,那么就会一直等待。
而导致两端都在等待。
*/
class TcpClient3
{
public static void main(String[] args) throws Exception
{
Socket s = new Socket(InetAddress.getLocalHost(),1000);
//定义读取键盘数据的流对象
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
//定义目的,将数据写入到socket输出流,发给服务器。
/* BufferedWriter bufOut =
new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
*/
//下面这句更简洁
//printWriter:即能接收字符也能接受字节流,还会自动刷新 可以解决本程序出现的问题。
PrintWriter out = new PrintWriter(s.getOutputStream());
//定义一个socket 读取流,读取服务端返回的大写信息
BufferedReader bufIn =
new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while((line=bufr.readLine()) != null)
{
if("over".equals(line))
break;
/*
注意这儿使用的是 缓冲流所以写完后如果不刷新,则数据在缓冲区中。
另:发的数据中没有回车符,而是把回车符之前的数据发送到服务端,
而服务端判断一行结束是以回车为标记。而这样服务端没有读到 回车标记
,服务端收数据后以为没有结束还会一直阻塞读取数据。
bufOut.write(line);
bufOut.newLine();
bufOut.flush(); //把缓冲区中的数据刷新
*/
//下面是使用了 printWriter的语句,更简洁。
out.println(line);
//写完后要读回来
String str = bufIn.readLine();
System.out.println("server:"+str);
}
bufr.close();
s.close();
}
}
/*
服务端:
BufferedReader:是阻塞式方法。它读到数据,而返回数据是以读到回车才返回数据,
如果没有读到回车还会一直阻塞读取。所以发发送方必须要发送一个包含回车符,否则
此处将会一直读取。
*/
class TcpServer3
{
public static void main(String[] args) throws Exception
{
ServerSocket ss = new ServerSocket(1000);
Socket s = ss.accept();
//读取socket流中的数据
BufferedReader bufIn =
new BufferedReader(new InputStreamReader(s.getInputStream()));
//将大写数据写入到socket输出流中,并发送给客户端
BufferedWriter bufOut =
new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line = null;
/*
BufferedReader:是阻塞式方法。它读到数据,而返回数据是以读到回车才返回数据,
如果没有读到回车还会一直阻塞读取。所以发发送方必须要发送一个包含回车符,否则
此处将会一直读取。
*/
while((line = bufIn.readLine()) != null)
{
bufOut.write(line.toUpperCase());
bufOut.newLine();
bufOut.flush(); //这个和客户发送数据一样。要有回车标记和刷新缓冲区。
}
s.close();
ss.close(); //关闭 socket 时 会在socket流中加入一个 -1 。服务端读到 -1 也会停止。
//如果不想这样,可以在服务器端进行判断 把最后判断的 标记 也发送过去。
}
}
/*
class TcpClient3
{
public static void main(String[] args) throws Exception
{
Socket s = new Socket(InetAddress.getLocalHost(),1000);
OutputStream out = s.getOutputStream();
InputStream in = s.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line = br.readLine()) != null)
{
if("over".equals(line))
break;
out.write(line.getBytes()); //写到流中
byte[] buf = new byte[1024]; //从流中读取返回的数据
int len = in.read(buf);
System.out.println(new String(buf,0,len));
}
s.shutdownOutput();
br.close();
s.close();
}
}
class TcpServer3
{
public static void main(String[] args) throws Exception
{
ServerSocket ss = new ServerSocket(1000);
Socket s = ss.accept();
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
String ip = s.getInetAddress().getHostName();
System.out.println(ip+"...主机连接服务器");
while(true)
{
byte[] buf = new byte[1024];
int len = in.read(buf);
String temp = new String(buf,0,len).toUpperCase();
System.out.println("收到:"+ temp);
out.write(temp.getBytes());
}
}
}
*/