写得不是很规范,但也写挺多的注释了。一般是可以看得懂的啦。没什么特别的功能,仅仅是群聊!ps:玩玩而已。直接贴代码。。。比较适合刚学Socket编程的看。界面的代码是用Netbean直接生成的,显得很笨重!

Code:

1. //====================Server.java================================= 
2. 
3. packagecc.nothing2012.blogServlet;  
4. 
5. importjava.io.DataInputStream;  
6. importjava.io.DataOutputStream;  
7. importjava.io.IOException;  
8. importjava.net.InetAddress;  
9. importjava.net.ServerSocket;  
10. importjava.net.Socket;  
11. importjava.util.Vector;  
12. 
13. publicclassServer{  
14. privateServerSocketserverSocket;  
15. privateSocketsocket;  
16. privatestaticVector<ServerObject>vector=newVector<ServerObject>();  
17. privateServerObjectserverObject;  
18. 
19. privatestaticVector<String>vecIPs=newVector<String>();//记录所有的IP对象 
20. publicServer(){  
21. try{  
22. newServerSocket(55555);  
23. "服务器已经启动!");//后台提示 
24. while(true){  
25. try{  
26. //一直在等待连接 
27. p(socket); 
28. finalInetAddressaddress=socket.getInetAddress();  
29. "那个丫的连接的IP:"+address);  
30. //打印连接前,登陆客户端的个数。 
31. newServerObject(socket);//说明一个客户端连接上了,新建对象线程。 
32. //往向量里面添加一个客户端。 
33. 
34. "add"+address.getHostAddress());  
35. "add"+address.getHostAddress());  
36. //启动一个线程 
37. "客户端个数:"+vector.size());//打印连接后,登陆客户端的个数。 
38. "IP个数:"+vecIPs.size());  
39. catch(IOExceptione){  
40. e.printStackTrace(); 
41. } 
42. } 
43. catch(IOExceptione){  
44. "服务器启动失败!");  
45. } 
46. } 
47. 
48. publicvoidp(Objecto){  
49. System.out.println(o); 
50. } 
51. 
52. publicstaticvoidmain(String[]args){  
53. newServer();  
54. } 
55. 
56. classServerObjectextendsThread{  
57. privateDataOutputStreamout=null;  
58. privateDataInputStreamin=null;  
59. privateSocketsocket=null;  
60. 
61. //每个连接过来的客户端,将初始化这样的一个对象。 
62. publicServerObject(Socketsocket){  
63. this.socket=socket;  
64. try{  
65. newDataInputStream(socket.getInputStream());  
66. newDataOutputStream(socket.getOutputStream());  
67. catch(IOExceptione){  
68. e.printStackTrace(); 
69. } 
70. 
71. } 
72. 
73. publicvoidinitIPs(){//无论是增加还是减少都用此方法来更新在线用户 
74. "";  
75. for(inti=0;i<vecIPs.size();i++){//vecIPs至少为1,故不判空 
76. //把ip地址都存放在一个字符串里面 
77. } 
78. try{  
79. for(inti=0;i<vector.size();i++){  
80. //输出信息给每个客户端。 
81. } 
82. catch(IOExceptione1){  
83. e1.printStackTrace(); 
84. } 
85. } 
86. //启动线程时,执行 
87. publicvoidrun(){  
88. booleanflag=true;//只是一个标志 
89. intm;  
90. //根据当前的在线用户刷新,在线的用户。每个对象只初始化一次! 
91. initIPs(); 
92. while(flag){  
93. try{  
94. //输入进来的流,简称输入流,拿到客户端的信息。 
95. "IP是"+socket.getInetAddress().getHostAddress()+"的"+message);//后台打印出来 
96. if(message.equals("exit")){//如果接收到"exit"字符串说明运行该线程的客户端断开了连接,则需退出该循环,退出线程 
97. false;//退出循环(指的是本通道关闭,该对象的进程结束) 
98. 
99. //try{ 
100. //Server.vecIPs.remove(this);//从vecIPs中除去本对象的IPs,估计会出错这儿。 
101. //}catch(NullPointerExceptionee){ 
102. //System.out.println("果然出错"); 
103. //ee.printStackTrace(); 
104. //} 
105. "add"+socket.getInetAddress().getHostAddress();//把此IP从ip向量表里咔嚓掉 
106. for(inti=0;i<vecIPs.size();i++){  
107. if(vecIPs.get(i).equals(tempIP)){  
108. vecIPs.remove(i); 
109. break;  
110. } 
111. } 
112. this);//当客户端关闭时,从Vector里除去本对象 
113. 
114. //重新初始化各个客户端。 
115. else{  
116. //返回共有多少个客户端目前。 
117. for(inti=0;i<m;i++){//给每个客户端发送同样的信息。 
118. //输出信息给每个客户端。 
119. } 
120. } 
121. catch(IOExceptione){  
122. e.printStackTrace(); 
123. } 
124. } 
125. } 
126. } 
127. } 
128.

Code:

1. //===================MyJFrame2.java=============================== 
2. 
3. packagecc.nothing2012.blogServlet;  
4. 
5. importjava.awt.event.ActionEvent;  
6. importjava.awt.event.ActionListener;  
7. importjava.awt.event.KeyAdapter;  
8. importjava.awt.event.KeyEvent;  
9. importjava.awt.event.WindowAdapter;  
10. importjava.awt.event.WindowEvent;  
11. importjava.io.DataInputStream;  
12. importjava.io.DataOutputStream;  
13. importjava.io.IOException;  
14. importjava.net.Socket;  
15. importjava.net.UnknownHostException;  
16. importjava.util.Timer;  
17. importjava.util.TimerTask;  
18. importjava.util.Vector;  
19. importjava.util.regex.Matcher;  
20. importjava.util.regex.Pattern;  
21. 
22. 
23. publicclassMyJrame2extendsjavax.swing.JFrameimplementsRunnable{  
24. publicstaticVector<String>vectorIP=newVector<String>();  
25. publicstaticVector<String>vectorIPtemp=newVector<String>();  
26. 
27. privateSocketsocket;  
28. privateDataInputStreamin;  
29. privateDataOutputStreamout;  
30. privatebooleanflag=true;//标志如果多个客户端则会出错。 
31. 
32. privatebooleanserverClose=false;//标识服务器端是否关闭,true为关闭,false为没关闭 
33. 
34. privatestaticfinallongserialVersionUID=1L;  
35. publicMyJrame2(){  
36. //用来初始化界面 
37. //连接服务器等操作 
38. //this.getRootPane().setDefaultButton(jToggleButton1); 
39. 
40. newTimer().schedule(newTimerTask(){  
41. publicvoidrun(){  
42. //for(inti=0;i<vectorIP.size();i++){ 
43. //System.out.println(vectorIP.get(i)); 
44. //} 
45. //System.out.println(vectorIP.size()); 
46. jList1.setListData(vectorIP); 
47. } 
48. 2000,3000);  
49. } 
50. publicStringgetMessage(){  
51. if(!(jTextField2.getText()).equals("")){//如果写的东西不为空 
52. if(!(jTextField1.getText()).equals("")){//判断是谁写的信息 
53. return(jTextField1.getText()+":"+jTextField2.getText());  
54. else{  
55. return("默认是骚包:"+jTextField2.getText());//无名氏默认是ClientX 
56. } 
57. else{//什么都没写 
58. return"";  
59. } 
60. } 
61. 
62. publicvoidsetMessage(Stringmessage){  
63. "/n");//添加信息并换行。 
64. } 
65. 
66. publicvoidcontorClient(){  
67. try{  
68. newSocket("xxx.xx.xxx.xxx",55555);//此处新建了一个Socket,并连接服务器 
69. //。通信从此位置开始。 
70. newActionListener(){//“发送”按钮监听 
71. publicvoidactionPerformed(ActionEvente){//监听按钮的方法。 
72. //必须实现的 
73. //。 
74. try{  
75. if(!serverClose){//第一次执行时,默认是开着的。之后,如果服务器开着, 
76. //即没有关闭,则发送下面内容 
77. //取得某人写的某些内容 
78. if(!message.equals("")){  
79. newDataOutputStream(socket  
80. .getOutputStream()); 
81. //把message通过s输出去 
82. "");//此处只有发送按钮在监听, 
83. //故发送之后 
84. //,内容理应删掉。 
85. } 
86. } 
87. catch(IOExceptionioe){  
88. ioe.printStackTrace(); 
89. } 
90. } 
91. }); 
92. this.addWindowListener(newWindowAdapter(){//监听客户端是否关闭,如果关闭, 
93. //则向服务器发送一个 
94. //“exit”字符串 
95. publicvoidwindowClosing(WindowEvente){  
96. try{  
97. if(serverClose){//serverClose的值一直都是false。 
98. //此处永远不会被执行。 
99. else{//因为监听到了窗口被关闭了。 
100. newDataOutputStream(socket  
101. .getOutputStream()); 
102. "exit");//既然关闭了,就发送个信号给服务器。 
103. //删除该客户端。 
104. } 
105. catch(IOExceptione1){  
106. e1.printStackTrace(); 
107. } 
108. } 
109. }); 
110. //只是实现了enter键的触发而已。 
111. newKeyAdapter(){  
112. publicvoidkeyPressed(KeyEventevent){  
113. if(event.getKeyCode()==KeyEvent.VK_ENTER){  
114. try{  
115. if(!serverClose){//第一次执行时,默认是开着的。之后,如果服务器开着,即没有关闭 
116. //,则发送下面内容 
117. //取得某人写的某些内容 
118. if(!message.equals("")){  
119. newDataOutputStream(socket  
120. .getOutputStream()); 
121. //把message通过s输出去 
122. "");//此处只有发送按钮在监听,故发送之后 
123. //,内容理应删掉。 
124. } 
125. } 
126. catch(IOExceptionioe){  
127. ioe.printStackTrace(); 
128. } 
129. } 
130. } 
131. }); 
132. 
133. newThread(this).start();//打开一个线程,即执行本类的run()函数。 
134. catch(UnknownHostExceptione){  
135. //打印出错信息而已,别无他意。 
136. catch(IOExceptione){  
137. true;  
138. "服务器不存在或未打开!");  
139. } 
140. } 
141. 
142. privatevoidinitComponents(){  
143. newjavax.swing.JLabel();  
144. newjavax.swing.JTextField();  
145. newjavax.swing.JLabel();  
146. newjavax.swing.JScrollPane();  
147. newjavax.swing.JTextArea();  
148. newjavax.swing.JTextField();  
149. newjavax.swing.JButton();  
150. newjavax.swing.JScrollPane();  
151. newjavax.swing.JList();  
152. setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 
153. "八卦聊天器");  
154. newjava.awt.Color(204,204,255));  
155. newjava.awt.Font("宋体",0,18));//NOI18N 
156. "请输入您的昵称:");  
157. newjava.awt.Font("宋体",0,18));//NOI18N 
158. newjava.awt.Color(204,204,255));  
159. newjava.awt.Font("宋体",0,18));//NOI18N 
160. "在线用户IP:");  
161. 20);  
162. 5);  
163. jScrollPane1.setViewportView(jTextArea1); 
164. newjava.awt.Font("宋体",0,18));//NOI18N 
165. "发送");  
166. newjava.awt.event.ActionListener(){  
167. publicvoidactionPerformed(java.awt.event.ActionEventevt){  
168. jButton1ActionPerformed(evt); 
169. } 
170. }); 
171. newjavax.swing.AbstractListModel(){  
172. privatestaticfinallongserialVersionUID=1L;  
173. "Item1","Item2","Item3","Item4","Item5"};  
174. publicintgetSize(){returnstrings.length;}  
175. publicObjectgetElementAt(inti){returnstrings[i];}  
176. }); 
177. jScrollPane2.setViewportView(jList1); 
178. newjavax.swing.GroupLayout(getContentPane());  
179. getContentPane().setLayout(layout); 
180. layout.setHorizontalGroup( 
181. layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
182. .addGroup(layout.createSequentialGroup() 
183. .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
184. .addGroup(layout.createSequentialGroup() 
185. 56,56,56)  
186. .addComponent(jLabel1) 
187. 18,18,18)  
188. 199,javax.swing.GroupLayout.PREFERRED_SIZE))  
189. .addGroup(layout.createSequentialGroup() 
190. 26,26,26)  
191. .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
192. 440,javax.swing.GroupLayout.PREFERRED_SIZE)  
193. 440,javax.swing.GroupLayout.PREFERRED_SIZE))  
194. .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED))) 
195. .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
196. .addGroup(layout.createSequentialGroup() 
197. 26,26,26)  
198. .addComponent(jLabel2)) 
199. .addGroup(layout.createSequentialGroup() 
200. 18,18,18)  
201. .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
202. 73,javax.swing.GroupLayout.PREFERRED_SIZE)  
203. 152,javax.swing.GroupLayout.PREFERRED_SIZE))))  
204. 24,Short.MAX_VALUE))  
205. ); 
206. layout.setVerticalGroup( 
207. layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
208. .addGroup(layout.createSequentialGroup() 
209. .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) 
210. .addGroup(layout.createSequentialGroup() 
211. .addContainerGap() 
212. 35,javax.swing.GroupLayout.PREFERRED_SIZE))  
213. .addGroup(javax.swing.GroupLayout.Alignment.LEADING,layout.createSequentialGroup() 
214. 44,44,44)  
215. .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 
216. 40,javax.swing.GroupLayout.PREFERRED_SIZE)  
217. .addComponent(jTextField1,javax.swing.GroupLayout.PREFERRED_SIZE,javax.swing.GroupLayout.DEFAULT_SIZE,javax.swing.GroupLayout.PREFERRED_SIZE)))) 
218. 18,18,18)  
219. false)  
220. .addComponent(jScrollPane2) 
221. 402,Short.MAX_VALUE))  
222. 18,18,18)  
223. .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) 
224. 63,javax.swing.GroupLayout.PREFERRED_SIZE)  
225. 48,javax.swing.GroupLayout.PREFERRED_SIZE))  
226. 39,39,39))  
227. ); 
228. pack(); 
229. } 
230. privatevoidjButton1ActionPerformed(java.awt.event.ActionEventevt){  
231. 
232. } 
233. publicvoidrun(){  
234. "MyIPis"
235. +socket.getInetAddress().getHostAddress()); 
236. 
237. while(flag){  
238. try{  
239. newDataInputStream(socket.getInputStream());  
240. if(vectorIPtemp.size()!=0){  
241. vectorIPtemp.removeAllElements(); 
242. } 
243. booleanisIPStr=false;  
244. //从服务器发过来的信息 
245. "从服务器获取的信息:"+message);  
246. //进行匹配看是否有ip地址 
247. Patternp; 
248. Matcherm; 
249. p=Pattern 
250. "add[0-9]{1,3}//.[0-9]{1,3}//.[0-9]{1,3}//.[0-9]{1,3}");  
251. //将信息进行匹配。 
252. while(m.find()){  
253. true;//说明是IP字符串。 
254. //取得类似add222.17.110.117的地址。 
255. //判断是否只有发送地址而已 
256. //StringisOnlyIP=message.substring(message2.length()); 
257. //if(!isOnlyIP.equals("")){ 
258. //setMessage(isOnlyIP);//输出到textArea 
259. //} 
260. //判断vectorIP中是否已存在该IP了。 
261. 3);  
262. vectorIPtemp.addElement(IP); 
263. /**由于一下只能判断增加去掉一样的IP的情况,故舍弃*/
264. //booleanisExist=false; 
265. //if(vectorIP!=null){ 
266. //for(inti=0;i<vectorIP.size();i++){ 
267. //if((vectorIP.get(i).equals(IP))){ 
268. 如果不一样,则继续遍历。如果一样,说明存在改变isExist的值。 
269. //isExist=true; 
270. //break;//遍历时,存在就退出。杯具:第一次是自己,存在。而第二个不存在了,且不判断;故出错。 
271. //} 
272. //} 
273. //} 
274. //if(isExist==false){//不存在就添加 
275. //vectorIP.addElement(IP); 
276. //} 
277. //先清空,再重新加载。 
278. } 
279. 
280. //如果执行了while里面的代码,则说明传过来的信息是做IP处理的。 
281. if(isIPStr==false){  
282. setMessage(message); 
283. else{  
284. //重新赋值给vectorIP 
285. } 
286. 
287. catch(IOExceptione){  
288. true;//服务器可能在有客户端存在的时候关闭,此时,客户端输入流会出错,刚执行此处 
289. "服务器关闭了!");  
290. false;//跳出循环 
291. } 
292. } 
293. } 
294. 
295. privatevoidjTextField1ActionPerformed(java.awt.event.ActionEventevt){  
296. // 
297. } 
298. 
299. privatevoidjTextField2ActionPerformed(java.awt.event.ActionEventevt){  
300. // 
301. } 
302. 
303. publicstaticvoidmain(Stringargs[]){  
304. newMyJrame2().setVisible(true);  
305. } 
306. privatejavax.swing.JButtonjButton1;  
307. privatejavax.swing.JLabeljLabel1;  
308. privatejavax.swing.JLabeljLabel2;  
309. privatejavax.swing.JListjList1;  
310. privatejavax.swing.JScrollPanejScrollPane1;  
311. privatejavax.swing.JScrollPanejScrollPane2;  
312. privatejavax.swing.JTextAreajTextArea1;  
313. privatejavax.swing.JTextFieldjTextField1;  
314. privatejavax.swing.JTextFieldjTextField2;  
315. } 
316.

==================

有个很明显的漏洞可以修改在线IP。不过也有个很好的解决方法,那就是在客户端先对信息进行匹配处理。

最后张图: