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();
}
}
}
}
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<Client> clients = new ArrayList<Client>();
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<Client> getClients() {
return clients;
}
public void setClients(List<Client> 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关闭资源