客户端
public class SimpleChatClient implements ActionListener {
JTextArea incoming;
JTextField outgoing;
JButton sendButton;
Socket sock;
BufferedReader reader;
PrintWriter writer;
public static void main(String[] args) {
new SimpleChatClient().go();
}
public void go(){
//创建GUI
JFrame frame = new JFrame("Ludicrously Simple Char Client");
JPanel mainPanel = new JPanel();
incoming = new JTextArea(15, 30); //消息显示窗口
incoming.setLineWrap(true);
incoming.setEditable(false);
JScrollPane qScroller = new JScrollPane(incoming);
qScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
qScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
outgoing = new JTextField(20); //文字发送窗口
sendButton = new JButton("Send"); //发送按钮
sendButton.addActionListener(this);
mainPanel.add(qScroller);
mainPanel.add(outgoing);
mainPanel.add(sendButton);
frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
frame.setSize(400, 500);
frame.setVisible(true);
//初始化网络连接
setUpNetworking();
//启动一个新线程,在新线程中读取服务器发送的信息
Thread readerThread = new Thread(new IncomingReader());
readerThread.start();
}
/**
* 初始化网络连接:
* 建立Socket,获取输入流,准备好输出流
*/
private void setUpNetworking(){
try {
/**
* 建立Socket:
* IP地址是本机回送地址,这样可以在一台电脑上测试各户端和服务器
* 端口号选取为5000,注意,端口号只能在1024~65535之间选取
*/
sock = new Socket("127.0.0.1", 5000);
//获取输入流,用于读取服务器的数据
InputStreamReader streamReader = new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(streamReader);
//准备好输出流,用于向服务器传送数据
writer = new PrintWriter(sock.getOutputStream());
System.out.println("networking established");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 按键响应函数
* 当按键按下时,向服务器发送消息
*/
@Override
public void actionPerformed(ActionEvent e) {
writer.println(outgoing.getText());
writer.flush();
outgoing.setText("");
outgoing.requestFocus();
}
public class IncomingReader implements Runnable {
@Override
public void run() {
String message;
try {
/**
* 在while循环中读取服务器传来的信息
* 若不为null,则将信息显示到控制台以及聊天窗口
*/
while((message = reader.readLine()) != null){
System.out.println("read" + message);
incoming.append(message + "\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务器
public class SimpleChatServer {
ArrayList clientOutputStreams;
public static void main(String[] args) {
new SimpleChatServer().go();
}
public void go(){
clientOutputStreams = new ArrayList();
try {
//建立一个服务器端的Socket,监听5000端口
ServerSocket serverSocket = new ServerSocket(5000);
while(true){
Socket clientSocket = serverSocket.accept();
//当有客户端连接时,获取输出流,维护一个包含所有输出流的列表
//每个输出流代表一个客户端
PrintWriter writer = new PrintWriter(clientSocket.getOutputStream());
clientOutputStreams.add(writer);
//创建一个新线程,在新线程中向所有的客户端发送消息
Thread t = new Thread(new ClientHandler(clientSocket));
t.start();
System.out.println("got a connection");
}
} catch (IOException e) {
e.printStackTrace();
}
}
public class ClientHandler implements Runnable {
BufferedReader reader;
Socket sock;
/**
* 构造方法:
* 初始化Socket和输入流
*/
public ClientHandler(Socket clientSocket){
sock = clientSocket;
try {
InputStreamReader isReader = new InputStreamReader(sock.getInputStream());
reader = new BufferedReader(isReader);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 读取消息,并发送给所有的客户端
*/
@Override
public void run() {
String message;
try {
while((message = reader.readLine()) != null){
System.out.println("read" + message);
tellEveryone(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 将消息发送给所有的客户端
*/
public void tellEveryone(String message){
Iterator it = clientOutputStreams.iterator();
while(it.hasNext()){
PrintWriter writer = (PrintWriter) it.next();
writer.println(message);
writer.flush();
}
}
}
参考:《Head First Java》