目录结构
1.导入依赖JSONObject(内部是用Hashmap来存储的,所以也可以不用JSONObject)
<!--将JSON转为字符串,将其他对象转为json。这里用来将socket传输的数据转换-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
2.服务端代码(ForumServer)
public static void main(String[] args) {
try {
System.out.println("开始绑定ip");
ServerSocket serverSocket = new ServerSocket(8181);
System.out.println("ip绑定完成,等待连接");
//每循环一次为一个请求连接,没有客户端请求连接时,阻塞循环,进入等待
while (true){
// 同一个socket,如果调用两次会报StreamCorruptedException,所以不要乱传socket
Socket accept = serverSocket.accept();
System.out.println("连接完成,开始获取字节数据");
InputStream inputStream = accept.getInputStream();
OutputStream outputStream = accept.getOutputStream();
System.out.println("获取字节数据完成,创建写线程和读线程");
new Thread(new Write(outputStream)).start();
new Thread(new Read(inputStream)).start();
System.out.println("创建写线程和读线程完成,可以读写");
}
} catch (IOException e) {
e.printStackTrace();
}
}
3.客户端代码(ForumClient)
public static void main(String[] args) {
try {
System.out.println("开始连接ip");
Socket socket = new Socket("localhost",8181);
System.out.println("ip连接完成,开始获取字节数据");
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
System.out.println("获取字节数据完成,创建写线程和读线程");
new Thread(new Write(outputStream)).start();
new Thread(new Read(inputStream)).start();
System.out.println("创建写线程和读线程完成,可以读写");
} catch (IOException e) {
e.printStackTrace();
}
}
4.读取消息(Read)
public class Read implements Runnable{
private InputStream inputStream;
public Read(InputStream inputStream){
this.inputStream = inputStream;
}
@Override
public void run() {
try {
ObjectInputStream objectInputStream = new ObjectInputStream(this.inputStream);
while(true){
System.out.println("读取消息:" + objectInputStream.readObject());
}
//闭流
//objectInputStream.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
5.发送消息(Write)
public class Write implements Runnable{
private OutputStream outputStream;
public Write(OutputStream outputStream){
this.outputStream = outputStream;
}
@Override
public void run() {
Scanner sc = new Scanner(System.in);
ObjectOutputStream objectOutputStream = null;
String str = null;
try {
objectOutputStream = new ObjectOutputStream(this.outputStream);
while (true){
JSONObject jsonObject = new JSONObject();
System.out.println("发消息:");
str = sc.next();
jsonObject.put("消息",str);
//发送消息
objectOutputStream.writeObject(jsonObject);
//刷新缓存
objectOutputStream.flush();
}
//后续添加结束聊天--闭流
//outputStream.close();
//sc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
6.结束
但是,因为发消息时传输的是HashMap,所以接收的消息也是JSON字符串。(这谁受得了)因此,我们对代码进行小小的改动一下(主要是对字节流部分的改动。当然了,根据具体需求,自己可以选择不同的格式)。
1.服务端代码(ForumServer)
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8181);
while(true){
Socket accept = serverSocket.accept();
//----------------------------------华丽的分割线--------------------------------------------
//这部分代码与下面的客户端一样
//在这里进行一下改动
InputStream inputStream = accept.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "GBK"));
OutputStream outputStream = accept.getOutputStream();
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(outputStream, "GBK"), true);
new Thread(new Read(bufferedReader)).start();
new Thread(new Write(printWriter)).start();
//----------------------------------华丽的分割线--------------------------------------------
}
} catch (IOException e) {
e.printStackTrace();
}
}
2.客户端代码(ForumClient)
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost", 8181);
//----------------------------------华丽的分割线--------------------------------------------
//这部分代码与服务端一样
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "GBK"));
OutputStream outputStream = socket.getOutputStream();
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(outputStream, "GBK"), true);
new Thread(new Read(bufferedReader)).start();
new Thread(new Write(printWriter)).start();
//----------------------------------华丽的分割线--------------------------------------------
} catch (IOException e) {
e.printStackTrace();
}
}
3.读取消息(Read)
public class Read implements Runnable{
private BufferedReader bufferedReader;
public Read(BufferedReader bufferedReader){
this.bufferedReader = bufferedReader;
}
@Override
public void run() {
try {
//从缓存中读取消息
String str = null;
while((str = bufferedReader.readLine()) != null){
System.out.println("读取消息:" + str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.发送消息(Write)
public class Write implements Runnable{
private PrintWriter printWriter;
public Write(PrintWriter printWriter){
this.printWriter = printWriter;
}
@Override
public void run() {
Scanner sc = new Scanner(System.in);
String str = null;
while (true){
System.out.println("发消息:");
str = sc.next();
//缓存中打印消息
printWriter.println(str);
}
//后续添加结束聊天--闭流
}
5.结束
后续可以根据自己需求增加心跳(在客户端增加,检测与服务器连接状态)、ip获取、群聊和结束聊天等功能。
*本人也是小白一枚,还请各位大佬指出不足之处。