Java Socket 编程——多线程网络聊天程序
首先,进行服务端的编程,作为服务端,编程主要按下面几个步骤进行:
// 1. 创建socket
ServerSocket ss = new ServerSocket(PortNumber);
Socket s = ss.accept(); //监听器,产生阻塞,直到有连接才停止阻塞。
// 2. 打开输入流、输出流
OutputStream os = s.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(os);
InputStream is = s.getInputStream();
// 3. 根据一定的协议读写数据
// 服务器 --> 客户
//os.write("Hello,I am Server!".getBytes());
bos.write("Hello,I am Server!".getBytes());
bos.flush(); //注意!!
// 服务器 <-- 客户
byte[] buf = new byte[100];
int len = is.read(buf);
System.out.println(new String(buf, 0, len));
// 4. 关系流和Socket
//os.close();
bos.close();
is.close();
s.close();
ss.close();
作为客户端则分为下面几个步骤,其实和服务端差不多,只是少了用ServerSocket进行监听。
// 1. 创建socket
Socket s = new Socket(InetAddress.getByName("localhost"),
PortNumber);
// 2. 打开输入流、输出流
OutputStream os = s.getOutputStream();
InputStream is = s.getInputStream();
// 3. 根据一定的协议读写数据
// 服务器 --> 客户
byte[] buf = new byte[100];
int len = is.read(buf);
System.out.println(new String(buf, 0, len));
// 服务器 <-- 客户
os.write("Hello,I am Client!".getBytes());
// 4. 关系流和Socket
os.close();
is.close();
s.close();
上面这些只是一个单线程的服务端->客户端的程序,只能进行一次通讯,多次通讯将被告知无法连接。
这时,我们就需要用到进程Thread进行编程,将其改造成多线程聊天程序,可以同时进行多客户端的连接与发送信息。
代码如下:
1 //Server.java
2
3 import java.awt.*;
4 import java.net.*;
5 import java.io.*;
6
7 public class Server extends Thread {
8 ServerSocket skt;
9
10 Socket Client[]=new Socket[10];;
11 Socket Client1=null;
12
13 int i = 0;
14
15 TextArea in;
16
17 int port,k=0,l=0;
18
19 //BufferedReader theInputStream;
20
21 PrintStream theOutputStream;
22
23 //String readin;
24
25 Face chat;
26
27 public Server(int port, Face chat) {
28 try {
29 this.port = port;
30 skt = new ServerSocket(port);
31 this.chat = chat;
32 } catch (IOException e) {
33 chat.ta.append(e.toString());
34 }
35 }
36
37 public void run() {
38
39 chat.ta.append("等待连线");
40
41 while (true) {
42 //System.out.print(""+i+"\n");
43 try {
44
45
46 Client[k] = skt.accept(); /**//* 接收客户连接 */
47
48 //当有客户端连接时就新建一个子线程
49
50
51 if (i < 2) {
52 ServerThread server[] = new ServerThread[10];
53 server[k]= new ServerThread(Client[k], this.chat, i);
54 l=server.length;
55 server[k].start();
56 chat.ta.append("客户端" + Client[k].getInetAddress() + "已连线\n");
57 /**//*theInputStream = new BufferedReader(new InputStreamReader(Client
58 .getInputStream()));*/
59 //for(int j=0;j<server.length;j++)
60 theOutputStream = new PrintStream(server[k].getClient().getOutputStream());
61 i = server[k].getI();
62 k++;
63 } else {
64 //theOutputStream = new PrintStream(null);
65 }
66
67 } catch (SocketException e) {
68 //chat.ta.append("连线中断!\n");
69
70 //chat.clientBtn.setEnabled(true);
71 //chat.serverBtn.setEnabled(true);
72 //chat.tfaddress.setEnabled(true);
73 //chat.tfport.setEnabled(true);
74 //try {
75
76 //skt.close();
77 //Client.close();
78 //} catch (IOException err) {
79 // chat.ta.append(err.toString());
80 //}
81 } catch (IOException e) {
82 chat.ta.append(e.toString());
83 }
84 }
85
86 }
87
88 public void dataout(String data) {
89 //for(int j=0;j<l;j++)
90 theOutputStream.println(data);
91 }
92 }
93
94 class ServerThread extends Thread {
95 ServerSocket skt;
96
97 Socket Client;
98
99 TextArea in;
100
101 int port;
102
103 int i;
104
105 BufferedReader theInputStream;
106
107 PrintStream theOutputStream;
108
109 String readin;
110
111 Face chat;
112
113//服务端子线程
114
115 public ServerThread(Socket s, Face chat, int i) {
116 this.i = ++i;
117 Client = s;
118 //this.port = port;
119 //skt = new ServerSocket(port);
120 this.chat = chat;
121
122 }
123
124 public int getI() {
125 return this.i;
126 }
127 public Socket getClient() {
128 return this.Client;
129 }
130 public void run() {
131
132 //chat.ta.append("等待连线");
133
134 try {
135 //Client = skt.accept(); /* 接收客户连接 */
136
137 //chat.ta.append("客户端" + Client.getInetAddress() + "已连线\n");
138 theInputStream = new BufferedReader(new InputStreamReader(Client
139 .getInputStream()));
140 theOutputStream = new PrintStream(Client.getOutputStream());
141
142 while (true) {
143 readin = theInputStream.readLine();
144 chat.ta.append(readin + "\n");
145 }
146
147 } catch (SocketException e) {
148 chat.ta.append("连线中断!\n");
149
150 chat.clientBtn.setEnabled(true);
151 chat.serverBtn.setEnabled(true);
152 chat.tfaddress.setEnabled(true);
153 chat.tfport.setEnabled(true);
154 try {
155 i--;
156 skt.close();
157 Client.close();
158 } catch (IOException err) {
159 chat.ta.append(err.toString());
160 }
161 } catch (IOException e) {
162 chat.ta.append(e.toString());
163 }
164 }
165
166 public void dataout(String data) {
167 theOutputStream.println(data);
168 }
169 }
170
171 //Client.java
172
173 import java.net.*;
174 import java.io.*;
175 import javax.swing.Timer;
176 class Client extends Thread {
177 Socket skt;
178 InetAddress host;
179 int port;
180
181 BufferedReader theInputStream;
182 PrintStream theOutputStream;
183 String readin;
184
185 Face chat;
186
187 public Client(String ip, int p, Face chat) {
188 try {
189 host = InetAddress.getByName(ip);
190 port = p;
191 this.chat = chat;
192 } catch (IOException e) {
193 chat.ta.append(e.toString());
194 }
195 }
196
197 public void run() {
198 try {
199 chat.ta.append("尝试连线");
200
201 skt = new Socket(host, port);
202 chat.ta.append("连线成功\n");
203
204 theInputStream = new BufferedReader(new InputStreamReader(skt
205 .getInputStream()));
206
207 theOutputStream = new PrintStream(skt.getOutputStream());
208 //Timer myTimer = new Timer();
209 while (true) {
210 readin = theInputStream.readLine();
211 chat.ta.append(readin + "\n");
212 }
213 } catch (SocketException e) {
214 chat.ta.append("连线中断!\n");
215 chat.clientBtn.setEnabled(true);
216 chat.serverBtn.setEnabled(true);
217 chat.tfaddress.setEnabled(true);
218 chat.tfport.setEnabled(true);
219 try {
220 skt.close();
221 } catch (IOException err) {
222 chat.ta.append(err.toString());
223 }
224 } catch (IOException e) {
225 chat.ta.append(e.toString());
226 }
227 }
228
229 public void dataout(String data) {
230 theOutputStream.println(data);
231 }
232 }
233
234//软件界面,进行按键监听调用。
235 //face.java
236
237 import java.awt.*;
238 import java.awt.event.*;
239
240 public class Face extends Frame {
241 /** *//**
242 *
243 */
244 private static final long serialVersionUID = 1L;
245 Button clientBtn, serverBtn;
246 TextArea ta;
247 TextField tfaddress, tfport, tftype;
248 int port;
249 Client client;
250 Server server;
251 boolean iamserver;
252 static Face frm;
253
254 public Face() {
255 clientBtn = new Button("客户端");
256 serverBtn = new Button("服务器");
257 ta = new TextArea("", 10, 50, TextArea.SCROLLBARS_BOTH);
258 tfaddress = new TextField("192.168.1.104", 20);
259 tfport = new TextField("2000");
260 tftype = new TextField(50);
261
262 tftype.addKeyListener(new TFListener());
263 ta.setEditable(false);
264
265 setLayout(new FlowLayout());
266 add(tfaddress);
267 add(tfport);
268 add(clientBtn);
269 add(serverBtn);
270 add(ta);
271 add(tftype);
272 setSize(400, 300);
273 setTitle("我的聊天室");
274 this.setVisible(true);
275
276 clientBtn.addActionListener(new ActionListener() {
277 public void actionPerformed(ActionEvent e) {
278
279 port = Integer.parseInt(tfport.getText());
280
281 client = new Client(tfaddress.getText(), port, frm);
282
283 client.start();
284
285 tfaddress.setEnabled(false);
286 tfport.setEnabled(false);
287 serverBtn.setEnabled(false);
288 clientBtn.setEnabled(false);
289 }
290 });
291
292 serverBtn.addActionListener(new ActionListener() {
293 public void actionPerformed(ActionEvent e) {
294
295 port = Integer.parseInt(tfport.getText());
296
297 server = new Server(port, frm);
298
299 server.start();
300
301 iamserver = true;
302 tfaddress.setText("成为服务器");
303
304 tfaddress.setEnabled(false);
305 tfport.setEnabled(false);
306 serverBtn.setEnabled(false);
307 clientBtn.setEnabled(false);
308 }
309 });
310
311 addWindowListener(new WindowAdapter() {
312 public void windowClosing(WindowEvent e) {
313 System.exit(0);
314 }
315 });
316
317 }
318
319 public static void main(String args[]) {
320 frm = new Face();
321 }
322
323 private class TFListener implements KeyListener {
324 public void keyPressed(KeyEvent e) {
325
326 if (e.getKeyCode() == KeyEvent.VK_ENTER) {
327
328 ta.append(">" + tftype.getText() + "\n");
329
330 if (iamserver)
331 server.dataout(tftype.getText());
332 else
333 client.dataout(tftype.getText());
334
335 tftype.setText("");
336 }
337 }
338
339 public void keyTyped(KeyEvent e) {
340 }
341
342 public void keyReleased(KeyEvent e) {
343 }
344 }
345
}