目的
利用Socket编程,完成一个对聊与群聊的小demo
利用多线程实现对聊
分析
在上一篇文章中,实现了客户端向服务器端发送固定信息,服务器端向客户端发送可变信息以及客户端向服务器端上次图片,而要实现两者相互传输数据应该怎么做呢?那么就要用到多线程
了
客户端
主线程
处理终端输入 发给服务器
class Client{
public static void main(String[] args) throws IOException {
Socket socket = new Socket("10.129.19.144",8080);
//用一个子线程处理服务器端数据
new Thread(new ClientThread(socket)).start();
//主线程处理终端输入 发送给服务器端
BufferedReader keyin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = keyin.readLine()) != null){
ps.println(line);
}
}
}
子线程
处理客户端接收服务器端数据
class ClientThread implements Runnable{
private Socket socket;
//保存socket对象
public ClientThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
//获取服务器端的输入流对象
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取数据
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络出错 请重新登录");
System.exit(-1);
}finally {
try{
if (br != null){
br.close();
}
if (socket != null){
socket.close();
}
}catch (IOException ex){
}
}
}
}
服务器端
主线程
处理终端输入 输出给服务器
class Server{
public static void main(String[] args) throws IOException{
ServerSocket ss = new ServerSocket(8080);
//获取客户端的socket
Socket socket = ss.accept();
//创建子线程
new ServerThread(socket).start();
//终端输入流对象
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//客户端的输出流对象
PrintStream ps = new PrintStream(socket.getOutputStream());
//读取终端的输入 将输入输出给客户端
String line = null;
while ((line = keyin.readLine()) != null){
ps.println(line);
}
}
}
子线程
处理服务器端接收客户端的数据
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
}catch (IOException e){
System.out.println("网络异常 请重新登录");
System.exit(-1);
}finally {
//关闭输入输出流
//关闭对应的socket连接
try {
if (br != null) {
br.close();
}
if (socket != null){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
实现群聊
分析
在群聊时,需要通过服务器端向各个客户端发送信息,即一个客户端现将信息发送给服务器端,服务器端在将信息发送给各个客户端,包括发送这个信息的客户端
如何实现通过服务器端同时向各个客户端发送信息呢?
在服务器端维护一个数组ArrayList
,用于管理维护各个客户端的socket
服务器端
主线程
添加数组和监听客户端连接
class Server{
//保存每一个连接过来的socket对象
public static ArrayList<Socket> sockets = new ArrayList<>();
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(6666);
//不停地等待服务器来连接
while (true){
Socket socket = ss.accept();
//当有客户端连接过来 就保存
sockets.add(socket);
//开启一个线程处理每个客户端的输入
new ServerThread(socket).start();
}
}
}
子线程
代码基本不变 进行一些小更改
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null){
//群发消息
//遍历Server维护的数组
for (Socket s:Server.sockets){
//向socket对应的客户端发生消息
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println(line);
}
}
}catch (IOException e){
System.out.println("网络异常 请重新登录");
System.exit(-1);
}finally {
//关闭输入输出流
//关闭对应的socket连接
try {
if (br != null) {
br.close();
}
if (socket != null){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
客户端
群聊客户端代码与私聊一模一样,所以就不再重复
心得体会
跟前面的内容裹在一起,让我十分地头疼,还是要再多些几遍才能熟悉