JavaSE版聊天室项目
JavaSE聊天室小项目
使用TCP编程实现客户端和服务器端的不断交互
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
/**
* 客户端
* */
public class ChatRoomClient {
public static void main(String[] args) {
try {
//创建Socket对象
Socket s = new Socket("127.0.0.1",12345);
//获取客户端通道的输出和输入流
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//客户端不断的发送消息
while(true) {
System.out.println("请输入消息:");
String msg = sc.nextLine();
//使用输出流发送过去
out.write(msg.getBytes());
//客户端读取服务器发送的消息
byte [] bys = new byte [1024];
int len = in.read(bys);
String msgStr = new String(bys, 0, len);
System.out.println(msgStr);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
* 服务器端
* */
public class ChatRoomServer {
public static void main(String[] args) {
try {
//创建服务器端Socket对象
ServerSocket ss = new ServerSocket(12345);
//监听客户端
Socket s = ss.accept();
//获取服务器端通道的输出和输入流
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//服务器端不断的读取消息和回复消息
while(true) {
//读消息
byte [] bys = new byte [1024];
int len = in.read(bys);
String msg = new String(bys, 0, len);
System.out.println(msg);
//回复消息
System.out.println("请回复消息:");
String msgStr = sc.nextLine();
out.write(msgStr.getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
这样做有问题,客户端和服务器端的读发消息都在一个线程,可能会出现互相等待的问题
改进:将读消息放在子线程里面(规定)
客户端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
/**
* 客户端
* @author dreamer_96
*/
public class ChatRoomClient {
public static void main(String[] args) {
try {
//创建Socket对象
Socket s = new Socket("127.0.0.1",12345);
//获取客户端通道的输出和输入流
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//开启读消息子线程
ClientThread ct = new ClientThread(in);
ct.start();
//客户端不断的发送消息
while(true) {
System.out.println("请输入消息:");
String msg = sc.nextLine();
//使用输出流发送过去
out.write(msg.getBytes());
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端读消息子线程
import java.io.IOException;
import java.io.InputStream;
/**
* 客户端读取消息的子线程
* @author dreamer_96
*/
public class ClientThread extends Thread {
private InputStream in ;
public ClientThread(InputStream in) {
this.in = in;
}
@Override
public void run() {
try {
while(true) {
//客户端不断读取服务器发送的消息
byte [] bys = new byte [1024];
int len = in.read(bys);
String msgStr = new String(bys, 0, len);
System.out.println(msgStr);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务器端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
* 服务器端
* @author dreamer_96
*/
public class ChatRoomServer {
public static void main(String[] args) {
try {
//创建服务器端Socket对象
ServerSocket ss = new ServerSocket(12345);
//监听客户端
Socket s = ss.accept();
//获取服务器端通道的输出和输入流
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//开启子线程
ServerThread st = new ServerThread(in);
st.start();
//服务器端不断的读取消息和回复消息
while(true) {
//回复消息
System.out.println("请回复消息:");
String msgStr = sc.nextLine();
out.write(msgStr.getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务器端读消息子线程
import java.io.IOException;
import java.io.InputStream;
/**
* 服务器端读取消息的子线程
* @author dreamer_96
*/
public class ServerThread extends Thread {
private InputStream in;
public ServerThread(InputStream in) {
this.in= in ;
}
@Override
public void run() {
try {
while(true) {
//读取客户端发送的消息
byte [] bys = new byte [1024];
int len = in.read(bys);
String msg = new String(bys, 0, len);
System.out.println(msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用ArrayList集合存储Socket对象
服务器端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;
/**
* 服务器端
* @author dreamer_96
*/
public class ChatRoomServer {
public static void main(String[] args) {
try {
//创建服务器端Socket对象
ServerSocket ss = new ServerSocket(12345);
//创建ArrayList集合;分别保存每个通道内的Socket对象
ArrayList<Socket> list = new ArrayList<Socket>();
System.out.println("等待客户端连接,请稍后....");
int i = 1;
while(true) {
//监听客户端
Socket s = ss.accept();
System.out.println("第"+(i++)+"个客户端已连接");
//服务器一监听到客户端,就跳添加到集合中
list.add(s);
//获取服务器端通道的输出和输入流
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
//开启子线程
// ServerThread st = new ServerThread(in);
ServerThread st = new ServerThread(s,list);
st.start();
}
/*//创建键盘录入对象
Scanner sc = new Scanner(System.in);
//服务器端不断的读取消息和回复消息
while(true) {
//回复消息
System.out.println("请回复消息:");
String msgStr = sc.nextLine();
out.write(msgStr.getBytes());
}*/
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务器端读消息子线程
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
/**
* 服务器端读取消息的子线程
* @author dreamer_96
*/
public class ServerThread extends Thread {
/*private InputStream in;
public ServerThread(InputStream in) {
this.in= in ;
}*/
private Socket s;
private ArrayList<Socket> list;
public ServerThread(Socket s, ArrayList<Socket> list) {
this.s = s;
this.list = list;
}
@Override
public void run() {
try {
//获取通道内的输入输出流
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
while(true) {
//读取客户端发送的消息
byte [] bys = new byte [1024];
int len = in.read(bys);
String msg = new String(bys, 0, len);
//msg现在的格式: 接收者:消息内容:发送者
System.out.println(msg);
//将消息拆分
String[] msgs = msg.split(":");
Socket socket = list.get(Integer.parseInt(msgs[0]));
//获取输出流,写过去
OutputStream os = socket.getOutputStream();
os.write((msgs[2]+"对你说"+msgs[1]).getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端不变,这样做依旧有缺点,我们要遵循开发规则 “高内聚,低耦合” ;所以我们使用HashMap集合添加用户并且增加服务器保存用户的子线程SaveUserThread
还没有评论,来说两句吧...