一个用Java编写的简单聊天室 用来学习Socket编程

/* *Create on Jan 29, 2009 *Copyright 2009 Quasar20063501.All Rights reserved * *weizhaozhe */ package client; import java.awt.*; 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.*; public class ChatClient extends Frame { private boolean connected = false; private DataOutputStream dos = null; private DataInputStream dis = null; private static final long serialVersionUID = 1L; private Socket s = null; private TextField tfWords = null; private TextArea taShow = null; public static void main(String args[]) { ChatClient cc = new ChatClient(); cc.launchFrame(); cc.Listen(); } public void launchFrame() { try { s = new Socket(InetAddress.getByName("localhost"), 8888); connected = true; dos = new DataOutputStream(s.getOutputStream()); dis = new DataInputStream(s.getInputStream()); } catch (IOException ioe) { System.out.println("服务器连接失败!"); ioe.printStackTrace(); } this.tfWords = new TextField(); this.taShow = new TextArea(); this.setTitle("Chatroom Client"); this.setLocation(700, 50); this.add(tfWords, BorderLayout.SOUTH); this.add(taShow, BorderLayout.NORTH); this.setSize(200, 250); this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { try { connected = false; dos.writeUTF("###Exit###"); dos.flush(); close(); System.exit(0); } catch (IOException ioe) { System.out.println("消息发送出错!"); ioe.printStackTrace(); } } }); this.setVisible(true); this.tfWords.addActionListener(new TFWordsListener()); } public void Listen() { new Thread(new ListenThread()).start(); } public void close() { try { if (dos != null) dos.close(); if (s != null) s.close(); } catch (IOException ioe) { ioe.printStackTrace(); System.out.println("客户端断开时出错!"); System.exit(-1); } } public class ListenThread implements Runnable{ public void run(){ while (connected) { try { String back = dis.readUTF(); //阻塞IO taShow.append(back); }catch(SocketException se){ System.out.println("谢谢使用!"); }catch (IOException e) { System.out.println("数据丢失!"); e.printStackTrace(); } } } } private class TFWordsListener implements ActionListener { public void actionPerformed(ActionEvent e) { String words = tfWords.getText().trim(); taShow.append("ME: " + words + "/n"); tfWords.setText(""); try { dos.writeUTF(words); } catch (IOException ioe) { System.out.println("发送出错!"); ioe.printStackTrace(); } } } } 代码如下:

服务器端:

 /* *Create on Jan 29, 2009 *Copyright 2009 Quasar20063501.All Rights reserved * *weizhaozhe */ package server; /** * 这个聊天室程序是基于TCP Socket的,其中,为了消除IO阻塞,采用了多线程的方式。 * * @author Quasar20063501 * @since Jan 29, 2009 * */ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.*; import java.util.List; import java.util.ArrayList; public class ChatServer { private List clients = new ArrayList(); private boolean started = false; private ServerSocket ss = null; private Client c = null; public ChatServer() { try { ss = new ServerSocket(8888); started = true; } catch (IOException ioe) { System.out.println("对不起,服务器不能启动!"); ioe.printStackTrace(); System.exit(-1); } } public void start() { try { Socket s = this.getSs().accept(); System.out.println("Here comes a client! "); if (s != null) { c = this.new Client(s, true); this.clients.add(c); new Thread(c).start(); // 线程始终没能停止!!!? c = null; } } catch (IOException e) { System.out.println("连接错误!"); e.printStackTrace(); } } public boolean isStarted() { return started; } public void setStarted(boolean started) { this.started = started; } public ServerSocket getSs() { return ss; } public void setSs(ServerSocket ss) { this.ss = ss; } public List getClients() { return clients; } public void setClients(List clients) { this.clients = clients; } public static void main(String args[]) { ChatServer cs = new ChatServer(); while (cs.isStarted()) { cs.start(); } } private class Client implements Runnable { private boolean connected = false; private Socket s = null; private DataInputStream dis = null; private DataOutputStream dos = null; public Client(Socket s, boolean connected) { this.s = s; this.connected = connected; } public void run() { InetAddress ip = null; int port = 9999; try { if (connected) { dis = new DataInputStream(s.getInputStream()); dos = new DataOutputStream(s.getOutputStream()); ip = s.getInetAddress(); port = s.getPort(); } while (connected) { String line = dis.readUTF(); if (line.equals("###Exit###")) { getClients().remove(this); // 当接收到推出的消息,移除客户端记录 line = "Bye-Bye!"; connected = false; } System.out.println("From: (" + ip.toString() + ":" + port + "): " + line); for (int i = 0; i < getClients().size(); i++) { if (this.equals(getClients().get(i))) { continue; } else { getClients().get(i).dos.writeUTF("From: (" + ip.toString() + ":" + port + "): " + line + "/n"); } } } } catch (IOException ioe) { System.out.println("客户端连接出错!"); ioe.printStackTrace(); } } } }

SOCKET 网络编程概要:

Socket又称为套接字,是两个程序进行双向数据传输的网络通

信的端点,一般由IP + PORT 构成。

(我们编程,通常采用的端口是大于1023的小于65535的数,1023之前一般被占用,如80被HTTP服务其占用,21被Telnet占用,23被FTP服务器占用等等)

Socket是一种底层的通信机制,通过Socket的数据是原始的字节流,必须经过两端的程序按照协议进行处理和解释。

其分为两类,面向连接的TCP/IP通信,和非连接的UDP数据报通信,我们的聊天室是采用TCP/IP面向连接编写的。

使用流程,在服务器端和客户端,分别使用ServerSocket和Socket,基本流程如下:

1创建套接字

2打开连接的IO

3按照协议读写

4关闭资源

你可能感兴趣的:(一个用Java编写的简单聊天室 用来学习Socket编程)