Java Socket 编程——多线程网络聊天程序

news/2024/7/8 4:16:51
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


}

http://www.niftyadmin.cn/n/3855208.html

相关文章

SQL Server 跨服务器 不同数据库之间复制表的数据的方法:

不同数据库之间复制表的数据的方法&#xff1a; 当表目标表存在时&#xff1a; insert into 目的数据库..表 select * from 源数据库..表 当目标表不存在时&#xff1a; select * into 目的数据库..表 from 源数据库..表 --如果在不同的SQL之间: insert into openrowset(sql…

Java多线程-----Socket通信

Java多线程-----Socket通信程序分Server和Client服务器端打开侦听的端口&#xff0c;一有客户端连接就创建两个新的线程来负责这个连接一个负责客户端发送的信息(ClientMsgCollectThread 类)&#xff0c;另一个负责通过该Socket发送数据&#xff08;ServerMsgSendThread &#…

算法学习-哈希表

之前在大学学习数据结构的时候&#xff0c;学过数组和链表。数组的优点就是可以直接定位&#xff0c;速度快&#xff0c;但是缺点就是插入删除&#xff0c;效率就慢了很多。链表的可以快速的插入删除&#xff0c;但是不能直接定位&#xff0c;需要遍历才可以。他们使用在不同的…

改变VM内存大小

-Xms512m -Xmx1024m -XX:PermSize128M -XX:MaxPermSize256M 转载于:https://blog.51cto.com/yaomingkai/1125760

数据库如何处理多对多的关系

数据库设计多对多关系的几种形态&#xff08;7种&#xff09; Posted on 2009-06-09 23:37 peterzb 阅读(739) 评论(1) 编辑 收藏 所属分类: 数据库技术数据库设计多对多关系的几种形态 前言&#xff1a;多对多关系至少需要3个表&#xff0c;我们把一个表叫做主表&#xff0c;一…

iOS: Device token and registerForRemoteNotificationTypes, didReceiveRemoteNotification

分类&#xff1a; Mobile iOS2012-04-18 19:25 244人阅读 评论(0) 收藏 举报Device token for an iPhone device生成之后就永远不变吗&#xff1f; 不是&#xff0c;if a device is wiped (应该是重装系统), it will get a new device token. 官方网站是这样写的&#xff1a; …

Java纯POJO类反射到Redis,反射到MySQL

这个是类定义&#xff0c;都是POJO类&#xff0c;纯数据 以下代码将POJO类反射到REDIS中&#xff0c;采用JSON序列化类数据。 public static <T> T save(T model, String indexName) throws Exception {String modelName model.getClass().getSimpleName();Jedis jedis …

PowerDesigner建模工具

PowerDesignerPowerDesigner建模工具 PowerDesigner是Sybase公司的CASE工具集&#xff0c;使用它可以方便地对管理信息系统进行分析设计&#xff0c;它几乎包括了数据库模型设计的全过程。 利用PowerDesigner可以制作数据流程图、概念数据模型、物理数据模型&#xff0c;可以生…