写得不是很规范,但也写挺多的注释了。一般是可以看得懂的啦。没什么特别的功能,仅仅是群聊!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。不过也有个很好的解决方法,那就是在客户端先对信息进行匹配处理。
最后张图: