package tf.thread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ChatServer {
private static final int PORT = 8888; // 端口号
private static List list = new ArrayList(); // 保存连接对象
private ExecutorService exec;
private ServerSocket server;
public static void main(String[] args) {
new ChatServer();
}
public ChatServer() {
try {
server = new ServerSocket(PORT);
exec = Executors.newCachedThreadPool();
System.out.println("服务器已启动!");
Socket client = null;
while (true) {
client = server.accept(); // 接收客户连接
list.add(client);
exec.execute(new ChatTask(client));
}
} catch (IOException e) {
e.printStackTrace();
}
}
static class ChatTask implements Runnable {
private Socket socket;
private BufferedReader br;
private PrintWriter pw;
private String msg;
public ChatTask(Socket socket) throws IOException {
this.socket = socket;
br = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
msg = "【" + this.socket.getInetAddress() + "】进入聊天室!当前聊天室有【"
+ list.size() + "】人";
sendMessage();
}
public void run() {
try {
while ((msg = br.readLine()) != null) {
if (msg.trim().equals("bye")) {
list.remove(socket);
br.close();
pw.close();
msg = "【" + socket.getInetAddress() + "】离开聊天室!当前聊天室有【"
+ list.size() + "】人";
socket.close();
sendMessage();
break;
} else {
msg = "【" + socket.getInetAddress() + "】说:" + msg;
sendMessage();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 群发消息给聊天室的所有人
*/
private void sendMessage() throws IOException {
System.out.println(msg);
for (Socket client : list) {
pw = new PrintWriter(client.getOutputStream(), true);
pw.println(msg);
}
}
}
}
聊天室客户端(输入bye可退出聊天室)
package tf.thread;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ChatClient {
private static final int PORT = 8888;
private static ExecutorService exec = Executors.newCachedThreadPool();
public static void main(String[] args) throws Exception {
new ChatClient();
}
public ChatClient() {
try {
Socket socket = new Socket("192.168.1.120", PORT);
exec.execute(new Sender(socket));
System.out
.println("【" + socket.getInetAddress() + "】您好,欢迎来到阿飞聊天室!");
BufferedReader br = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
String msg;
while ((msg = br.readLine()) != null) {
System.out.println(msg);
}
} catch (Exception e) {
}
}
/**
* 客户端线程获取控制台输入消息
*/
static class Sender implements Runnable {
private Socket socket;
public Sender(Socket socket) {
this.socket = socket;
}
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(
System.in));
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
String msg;
while (true) {
msg = br.readLine();
pw.println(msg);
if (msg.trim().equals("bye")) {
pw.close();
br.close();
exec.shutdownNow();
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
分享到:
2009-04-11 23:04
浏览 6903
论坛回复 / 浏览 (7 / 23449)
评论
10 楼
panshunchang
2011-10-28
private void sendMessage() throws IOException {
System.out.println(msg);
for (Socket client : list) {
pw = new PrintWriter(client.getOutputStream(), true);
pw.print(msg);
}
}
使用这个个pw.print(msg)方法不能正常显示消息
而使用这个pw.println(msg)却可以;
9 楼
panshunchang
2011-10-28
有个问题问问:
ChatServer 代码里,如果把
/**
* 群发消息给聊天室的所有人
*/
private void sendMessage() throws IOException {
System.out.println(msg);
for (Socket client : list) {
pw = new PrintWriter(client.getOutputStream(), true);
pw.print(msg); //使用个方法缺不能正常显示消息 //而使用这个pw.println(msg)却可以;
}
}
8 楼
panshunchang
2011-10-28
有个问题问问:
ChatServer 代码里,如果把
/**
* 群发消息给聊天室的所有人
*/
private void sendMessage() throws IOException {
System.out.println(msg);
for (Socket client : list) {
pw = new PrintWriter(client.getOutputStream(), true);
pw.print(msg); //使用个方法缺不能正常显示消息 //而使用这个pw.println(msg)却可以;
}
}
7 楼
fjlyxx
2009-04-16
呵呵,给你个建议.你可以这样写.当前一个线程拥有这个SOCKET,如果有请求那么这个拥有SOCKET的线程去现场池里面找一条可以用的线程并且把SOCKET给他,这样的话你就避免了线程的问题.如果要群发的话那么你应该考虑用消息通信机制,避免让消息去驱动连接.
6 楼
reallyafei
2009-04-15
LZ,
private static List<Socket> list = new ArrayList<Socket>(); // 保存连接对象
服务器端有多个线程都会读list,貌似并非线程安全...
恩,确实应该考虑同步问题,可以用
CopyOnWriteArrayList替换ArrayList
5 楼
finux
2009-04-15
LZ,
private static List<Socket> list = new ArrayList<Socket>(); // 保存连接对象
服务器端有多个线程都会读list,貌似并非线程安全...
4 楼
reallyafei
2009-04-15
lvp 写道
SOCKET 写一个聊天室也蛮有意思的!加油!
是挺有意思的,看你写的聊天室,很不错呢
向你学习!
3 楼
lvp
2009-04-15
SOCKET 写一个聊天室也蛮有意思的!加油!
2 楼
reallyafei
2009-04-13
fjlyxx 写道
mina 几句就搞定了的
哈哈,实现功能的代码确实没多少,我只是加了一些进入聊天室提醒或离开聊天室提醒以及清除资源的代码,所以显得多了。见笑了!
1 楼
fjlyxx
2009-04-12
mina 几句就搞定了的