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 



 }