首先是服务端,都是我自己一点点复制,修改,加备注的,真心不太会这个只是试过可以互通,因为没有多余的电脑陪我通讯,退出聊天室的代码不确定是否正确,我一个人操作的时候,报过错,可以直接复制所有代码,绝对可以达到互通效果,记得改端口号和ip地址,服务端只需改端口,客户端有端口的IP地址
服务端代码
package com.muzi.message;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
/**
* Scocket通讯服务端
* @author 木子
*/
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
/**
* 聊天室服务端 运行服务端的ServerSocket有两个主要作用 1.申请服务端口,客户端就是通过该端口于服务端口建立链接的
* 1,监听申请的服务接口,一旦一个客户端通过该端口于服务器端链接,ServerSocket 就会主动创建一个Socket于客户端通训
*/
import java.util.List;
public class FuWu
{
// 创建Socket通讯(我自己的理解,百度没搜到翻译)
private ServerSocket server;
// 用集合储存客户端发来的信息,以便群聊时全部显示
private List
// 创建构造方法,用来初始化客户端
public FuWu() throws IOException
{
// 初始化ServerSocket要同时指定服务器端口号,如果端口被占用,那么就会抛出异常
server = new ServerSocket(9999);
// 初始化存储集合
list = new ArrayList
}
// 监听端口等待客户端链接
public void start()
{
try
{
while (true)
{
System.out.println("等待小主宠幸ing...");
// ServerSocket的accept方法是一个阻塞方法;作用是监听端口,等待客户端链接,线程才能执行
Socket socket = server.accept();
System.out.println("一位小主准备进入后宫。");
// 阻塞结束,根据下面的的ClientHandler进行链接(可能是这样我的理解)
ClientHandler hander = new ClientHandler(socket);
Thread t = new Thread(hander);
t.start();
}
}
catch (Exception e)
{
}
}
public static void main(String[] args)
{
try
{
// 共享资源尝试链接
FuWu server = new FuWu();
// 调用FuWu中的start方法
server.start();
}
catch (Exception e)
{
// 如果链接失败
System.out.println("小主走到门口又回宫了!");
e.printStackTrace();
}
}
// 用来与指定客户端链接 实现Runnable接口
private class ClientHandler implements Runnable
{
private Socket socket;
// 客户端的地址信息
private String host;
// 当前线程通过这个socket与指定客户端交互
public ClientHandler(Socket socket)
{
this.socket = socket;
// 获取远端计算机的ip地址
InetAddress address = socket.getInetAddress();
// 获取远端计算机的ip地址的字符串格式
host = address.getHostAddress();
}
public void run()
{
// 向文本输出流打印对象的格式化表示形式。
PrintWriter pp = null;
try
{
System.out.println(host + "小主,进入后宫中!");
/**
* 处理与刚刚进入链接的客户端进行远程交互工作 InputStream的getInputStream();
* 该方法可以获取一个输入流,通过该流可以读取 到远端计算机发送过来的数据;
*/
// 这是接受客户端发来的信息
InputStream ss = socket.getInputStream();
// 转换成字节流
InputStreamReader zj = new InputStreamReader(ss, "UTF-8");
// 缓冲流
BufferedReader hcq = new BufferedReader(zj);
/*-----------------分割-----------------------*/
// 这是向客户端发送信息
OutputStream out = socket.getOutputStream();
OutputStreamWriter wr = new OutputStreamWriter(out, "UTF-8");
// 将向客户端发送的信息存储到之前设定的文本流
pp = new PrintWriter(wr, true);
// 线程锁,一次只能有一个客户端发送信息,需要线程抢夺资源
synchronized (out)
{
list.add(pp);
}
// 用来接收客户端发来的信息
String sk = null;
/*
* 读取客户端发送过来消息的br.readline(); 方法在客户端断开链接时;这里运行的结果也不同
* linux的客户端断开链接时;该方法会返回null windiws的客户端断开链接时,该方法会直接抛出异常
*/
// 在客户端发来的信息不等于空执行
while (hcq.readLine() != null)
{
// 接受输出
sk = hcq.readLine();
System.out.println(host + "小主:" + sk);
// 线程锁,就像QQ聊天差不多,如果有多个人同时说话
synchronized (out)
{
// o将list里的信息遍历
for (PrintWriter o : list)
{
o.println(host + "小主:" + sk);
// 如果客户端说白白就自动退出
if (sk.equals("白白"))
{
break;
}
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
// 处理客户端断开链接后的操作
// 将该客户端的输出流从共享集合中删除
synchronized (list)
{
// 删除客户端发送的信息流
list.remove(pp);
}
try
{
// 关闭指定客户端
socket.close();
}
catch (Exception e2)
{
e2.printStackTrace();
}
System.out.println(host + "小主回宫!");
}
}
}
}
客户端
package com.muzi.message;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
/**
* Scocket客户端
* @author 木子
*/
public class Client
{
// socket封装了tcp通讯协议
private Socket socket;
// 重写构造方法,用于初始化客户端
// 客户端开始工作的方法
public Client() throws Exception
{
/*
* 实例化Socket的过程就是链接远端计算机的过程;这里需要传入两个 参数 1.服务端的IP地址信息 2.服务端的端口
* 通过IP可以找到服务端的计算机,通过端口可以链接到运行在服务器端 计算机上的
*/
System.out.println("正在前往后宫ing。。。");
socket = new Socket("192.168.43.212", 9999);
System.out.println("已进入后宫");
}
public void start()
{
try
{
// 启动用来读取服务端消息的线程
ServerHandler hander = new ServerHandler();
Thread t = new Thread(hander);
t.start();
//动态输入
Scanner scan = new Scanner(System.in);
/*
* socket方法 outputStream,getOutputStream() ; 该方法会获取一个输出流,
* 通过该输出流写出的数据会发送到远端计算机
*/
//写入的数据,通过
OutputStream out = socket.getOutputStream();
OutputStreamWriter id = new OutputStreamWriter(out, "UTF-8");
PrintWriter pe = new PrintWriter(id);
long last = System.currentTimeMillis();
while (true)
{
String ss = scan.nextLine();
if (System.currentTimeMillis() - last >= 1000)
{
pe.println(ss);
last = System.currentTimeMillis();
}
else
{
System.out.println("你输入过快");
}
pe.flush();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
try
{
Client client = new Client();
client.start();
}
catch (Exception e)
{
System.out.println("客户端启动失败");
e.printStackTrace();
}
}
/*
* 该线程用来循环读取客户端发送过来的每一条消息 并输出到控制台;
*/
private class ServerHandler implements Runnable
{
public void run()
{
try
{
InputStream in = socket.getInputStream();
InputStreamReader is = new InputStreamReader(in, "UTF-8");
BufferedReader br = new BufferedReader(is);
String message = null;
// 读取服务端发送过来的消息并输出到控制台
while ((message = br.readLine()) != null)
{
System.out.println(message);
}
}
catch (Exception e)
{
}
}
}
}