目录
一、转换为DataOutputStream和DataInputStream
二、转换为InputStreamReader和OutputStreamWriter
三、由(二)转换为BufferedReader和PrintWriter(为啥不是BufferedWriter?
四、总结我们不难看出我的用以是啥,就是把字节流转换为字符流操作嘛。
与Socket有关的类有两种:
- 一种是Serversocket和socket(基于TCP协议,属于长连接,既一直保持连接不断开,除非主动断开或网络原因断开)
- 另一种是DatagramSocket(基于UDP协议,属于短连接,既发送数据包之后就断开,不用通知服务端)
我们要学习的是第一种ServerSocket和Scoket。
首先,我们要讲一下流相关的知识,因为TCP的Socket(以下用Socket代表TCP的Socket)是通过数据流来传递数据的。
从Socket中获取流,总是从Socket这个类中得到的,所以我们在连接过程中基本都是操作Socket这个类,
Socket流(inputstream和outputstream)获取:
private static finally String ip = "127.0.0.1";
private static finally String port = "9520";
//这个端口port只要与电脑上软件的端口不相同,与ServerScoket相同就行了
从Socket获取流:
Socket socket = new Socket( ip ,port );
OutputStream out = socket.getOutputStream();
//这样子我们就能从Server端到Client端传数据或者从Client端到Server端写入数据
InputStream in = socket.getInputStream();
//这样子我们就能从Server端到Client端传数据或者从Client端到Server端读取数据
流的处理:
我们可以把得到的输入输出流进行转换成更容易操作的流对象。
一、转换为DataOutputStream和DataInputStream
String info ="我是要发送的数据,嘻嘻";
DataOutputStream dout =new OutputStreamWriter(out);
DataInputStreamdin = new DataInputStream(in);
其实说这个我只是想说一个方法而已,哈哈哈,这个方法可以解决中文乱码问题
ds.writeUTF(info);//该方法读入一个字符串做参数
d.readUTF();//该方法阻塞,直到收到DataOutputStream发送过来的数据
PS:记住这是配套使用的,不要傻傻顺便用,因为这两个方法实现方法有点特殊
二、转换为InputStreamReader和OutputStreamWriter
InputStreamReader为是字节流通向字符流的桥梁
OutputStreamWriter是字符流通向字节流的桥梁
InputStreamReaderiReader = new InputStreamReader(in);//这里使用输入流作为参数
OutputStreamWriter oWriter = new OutputStreamWriter(out);//这里使用输出流作为参数
同时我们也可以设置两个流的字符集耶。。。
String charsetName = "utf-8";
InputStreamReader iReader = new InputStreamReader(in ,charsetName);//创建使用给定字符集的
OutputStreamWriter oWriter = new OutputStreamWriter(out ,charsetName);//创建使用给定字符集的
PS:为提高效率,我们一般不直接操作这两个类,而是借助下面两个类来操作,
这里的参数输入流输出流可以是Scoket的到输入输出流哦!
三、由(二)转换为BufferedReader和PrintWriter(为啥不是BufferedWriter?
因为BufferedWriter一般也是转换为PrintWriter使用的,所以直接讲PrintWriter吧)
BufferedReader reader = newBufferedReader(iReader);
PrintWriter writer = new PrintWriter(oWriter);
PrintWriter writer = new PrintWriter(oWriter , true);//设置PrintWriter自动刷新
这里我也要说两个方法
String info ="有一次,我是要发送的数据,嘻嘻";
writer.println(info);//这样子就发送好了,自带换行功能
writer.print("out" + "\n");//手动换行模式,哈哈哈
writer.write"out" + "\n");//有没发现这两个都可以做输出啊,我也不知道有啥区别,不深究他们啦
writer.println();//换行函数
writer.flush();//刷新缓冲区
String result = reader.readLine();
PS:作为流我们要写入数据之后是要flush一下的,但是Socket下,我就没有看到flush起作用
倒是我们要手动换行才能将数据刷行,这个要记好了,我被坑了两天(服务端一直接收不到数据),都没有找出原因,最后看其他人写的demo才恍然大悟。
四、总结我们不难看出我的用以是啥,就是把字节流转换为字符流操作嘛。
思路有两个:
一、从Socket获取流转换为(一)中的两个流接受和发送
二、从Socket获取流转换为(二)→(三),字符串更容易操作,而不是操作字节流
有了这些知识希望你能避开我遇到的那些坑。
说完了流的事,我们继续说下实例吧。
服务端:
package server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class MySocketService {
private static ServerSocket server;
private static Socket s;
private static final int port = 9520;
public static void main(String[] aa) {
InputStream in = null;
InputStreamReader reader = null;
BufferedReader buf = null;
try {
server = new ServerSocket(port);
System.out.println("服务端监听");
s = server.accept();
in = s.getInputStream();// 获取输出流
System.out.println("远程地址:" + s.getRemoteSocketAddress());
System.out.println("本地端口:" + s.getLocalPort());
System.out.println("远程端口:" + s.getPort());
reader = new InputStreamReader(in,"utf-8");
buf = new BufferedReader(reader);
System.out.println("开始读取信息.....");
String info;
while (true) {
info = buf.readLine();
buf.readLine();
System.out.println("客户端信息:" + info);
if (info.equals("bye")) {
break;
}
}
System.out.println("客户端信息" + info);
System.out.println("接收信息完成");
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}// 创建绑定到特定端口的服务器套接字。
finally {
try {
buf.close();
reader.close();
in.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
客户端:
package client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author 小辉辉-华南理工大学广州学院
*/
public class MySocket {
private static Socket client;
public static final int port = 9520;
public static final String ip = "127.0.0.1";
public static void main(String[] args) {
String info = null;
OutputStream out = null;
OutputStreamWriter ow = null;
PrintWriter pw = null;
try {
client = new Socket(ip, port);
out = client.getOutputStream();
ow = new OutputStreamWriter(out, "utf8");
pw = new PrintWriter(ow, true);
while (true) {
// info = scanner.nextLine();
System.out.print("客户端信息输入:");
info = new BufferedReader(new InputStreamReader(System.in,
"utf-8")).readLine();
System.out.println("服务器信息:"+info);
pw.println(info);
//pw.print("out");
pw.println();
// pw.print(info);
// pw.write(info);
if (info.equals("bye")) {
break;
}
// pw.flush();
}
pw.printf("--client--");
pw.flush();
} catch (IOException ex) {
Logger.getLogger(MySocket.class.getName()).log(Level.SEVERE, null,
ex);
}
}
}
在最后我说一下socket断开的是吧。像我这样子用循环写读数据的记得不要输入流输出流关了,因为流一关,socket也会关闭的,我debuger的时候慢慢看变化,当与Socket有关的流一关闭,Socket的isClose属性就会变为true;接着你就好好看报错吧。我上面代码没有写关闭,因为测试代码嘛。。。。关闭时调用Socket的close方法,还有就是把流关闭了。碎觉。掰掰