今天复习了socket网络编程,感觉并没有一开始接触时的难度了,顺带多线程也复习了一下下
依赖的jar包
主要有三个类,三个线程,分别是:
服务器端等待新客户端连接线程,
从客户端接收数据线程,
客户端接收服务端数据线程。
第一个是服务端Server:
public class Server implements Runnable {
private int port = 8422;
private List<ClientSocket> clients;
private ServerSocket server;
private static int clientId = 1;
public static void main(String[] args) throws Exception {
new Server();
}
public Server() throws IOException {
server = new ServerSocket(10086);// 1024-65535的某个端口
clients = new ArrayList<ClientSocket>();
new Thread(this).start();
System.out.println("server starting");
}
public void sendToAll(String message) throws IOException {
for (ClientSocket client : clients) {
client.sendMsg(message);
}
}
@Override
public void run() {
try {
while (true) {
// 等待 客户端连接
Socket client = server.accept();
// 将连接的客户端初始化并运行
ClientSocket clientSocket = new ClientSocket(client, this, clientId);
clientId++;
clientSocket.start();
// 添加到客户端连接列表中
clients.add(clientSocket);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客户端操作类:
public class ClientSocket extends Thread {
private DataInputStream dis;
private DataOutputStream dos;
private Socket clientSocket;
private Server server;
private int clientId;
public ClientSocket(Socket clientSocket, Server server, int clientId) throws Exception {
super();
this.clientSocket = clientSocket;
this.server = server;
this.clientId = clientId;
this.dis = new DataInputStream(clientSocket.getInputStream());
this.dos = new DataOutputStream(clientSocket.getOutputStream());
}
public void close() throws IOException {
dis.close();
dos.close();
clientSocket.close();
}
public void sendMsg(String message) throws IOException {
dos.writeUTF(message);
}
@Override
public void run() {
try {
while (true) {
server.sendToAll(dis.readUTF());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客户端类:
public class Client extends JFrame implements Runnable {
private JButton send;
private JButton register;
private JTextArea content;
private JTextField message;
private JTextField name;
private JLabel label;
private JLabel username;
private DataOutputStream dos;
private DataInputStream dis;
private Socket socket;
public static void main(String[] args) throws Exception {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Client frame = new Client();
Thread thread = new Thread(frame);
thread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Client() throws UnknownHostException, IOException {
socket = new Socket("127.0.0.1", 10086);
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
setLayout(new BorderLayout());
send = new JButton("发送消息");
register = new JButton("登录");
content = new JTextArea();
message = new JTextField(27);
name = new JTextField(10);
username = new JLabel();
label = new JLabel("输入用户名");
JPanel panel = new JPanel();
JPanel panel2 = new JPanel();
panel.setLayout(new BorderLayout());
panel2.setLayout(new BorderLayout());
panel.add(message, BorderLayout.WEST);
panel.add(send, BorderLayout.EAST);
panel2.add(label, BorderLayout.WEST);
panel2.add(name, BorderLayout.CENTER);
panel2.add(register, BorderLayout.EAST);
add(content, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
add(panel2, BorderLayout.NORTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
setVisible(true);
send.addActionListener(new sendListener());
register.addActionListener(new sendListener());
}
private class sendListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
try {
if(e.getSource().equals(send)){
Message msg = new Message(Message.SendMSG,message.getText(),username.getText(),"");
dos.writeUTF(msg.toJSON());
message.setText("");
}
if(e.getSource().equals(register)){
username.setText(name.getText());
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
@Override
public void run() {
try {
while (true) {
Message message = Message.getInstance(dis.readUTF());
content.append(message.from+" 说:" +message.getBody()+ "\n");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
用swing的界面....别嫌弃low,其中可以更好的实现,用单例管理线程池等等,可以自己实现,我把原理实现了就好嘻嘻。
中间的message是:
public class Message {
public final static String LOGIN = "LOGIN";
public final static String LOGOUT = "LOGOUT";
public final static String SendMSG = "SENDMSG";
String type;
String body;
String from;
String to;
public Message() {
// TODO Auto-generated constructor stub
}
public Message(String type, String body, String from, String to) {
super();
this.type = type;
this.body = body;
this.from = from;
this.to = to;
}
public static Message getInstance(String jsonStr)
{
Message instance = null;
try {
JSONObject object = JSONObject.fromString(jsonStr);
instance = (Message) JSONObject.toBean(object, Message.class);
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
public String toJSON()
{
JSONObject object = JSONObject.fromBean(this);
return object.toString();
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public static String getLogin() {
return LOGIN;
}
public static String getLogout() {
return LOGOUT;
}
}
最后看效果: