这是一个简单的qq聊天程序,实现了接收和发送数据的功能,先把代码亮一下
/*
* 服务器端代码
*/
package com.wangweijun.chat;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
public class ChatServer {
List<Client> clients = new ArrayList<Client>();
public void init() {
try {
ServerSocket serverSocket = new ServerSocket(8888);
// accept()为阻塞性的方法
while (true) {
int index = 1;
Socket socket = serverSocket.accept();
if (socket != null) {
System.out.println("a client connected");
Client client = new Client(socket, index++);
clients.add(client);
System.out.println("init clients size = " + clients.size());
client.start();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
class Client extends Thread {
int id;
Socket socket = null;
DataInputStream dis = null;
DataOutputStream dos = null;
public Client(Socket socket, int id) {
this.socket = socket;
this.id = id;
try {
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
// readUTF()为阻塞性的方法
try {
while (true) {
String content = dis.readUTF();
System.out.println(content);
//群发
for (int i = 0; i < clients.size(); i++) {
Client c = clients.get(i);
if(!c.equals(this)){
DataOutputStream dos = c.getDos();
dos.writeUTF(content);
}
}
}
} catch (SocketException e) {
System.out.println("一个客户退出了哈");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
dis.close();
dos.close();
socket.close();
clients.remove(this);
System.out.println("clients size = " + clients.size());
} catch (IOException e) {
e.printStackTrace();
}
}
}
public List<Client> getClients() {
return clients;
}
public DataOutputStream getDos() {
return dos;
}
}
public static void main(String[] args) {
new ChatServer().init();
}
}
/*
* 客户端代码
*/
package com.wangweijun.chat;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
public class ChatClient extends Frame {
TextArea ta = null;
TextField tf = null;
Socket socket = null;
DataOutputStream dos = null;
DataInputStream dis = null;
String content = "";
public static void main(String[] args) {
new ChatClient().launch();
}
public void launch(){
connet();
this.setTitle("腾讯qq");
this.setLocation(400, 300);
this.setSize(300, 400);
ta = new TextArea();
tf = new TextField();
this.add(ta, BorderLayout.NORTH);
this.add(tf, BorderLayout.SOUTH);
this.pack();
this.setVisible(true);
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
tf.addActionListener(new TextFieldListener());
//启动接收线程
new ReceiverThread().start();
}
class ReceiverThread extends Thread {
@Override
public void run() {
try {
while(true){
String read = dis.readUTF();
content = content + read + "/n";
ta.setText(content);
System.out.println(read);
}
}catch(SocketException e){
System.out.println("服务器已经停止服务");
return;
}catch (IOException e1) {
e1.printStackTrace();
}finally{
try {
dos.close();
dis.close();
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
private class TextFieldListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
content = content + tf.getText() + "/n";
ta.setText(content);
send(tf.getText());
tf.setText("");
}
}
public void send(String content){
try {
dos.writeUTF(content);
} catch (IOException e) {
e.printStackTrace();
}
}
public void connet(){
try {
socket = new Socket("127.0.0.1", 8888);
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
经本人测试运行正常,写一点点心得:聊天程序里有几个阻塞性的方法,一个是ServerSocket中的accept(),
接收客户端请求,另一个是DataInputStream中的readUTF(),从客户端读取数据,由于要不断循环的接收客户端请求,接收到客户端请求后,又要不断循环的接收客户端发送过来的数据,所以这两个方法必须处于不同的线程中,我觉得这是本程序的难点