============================================================
1.实现server和client模型程序
============================================================
实现原理:
============================================================
服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,
在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),
等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。
============================================================
客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,
关闭Socket。客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。
============================================================
服务器端代码:
1 package com.b510.socket1703;
2
3 import java.io.*;
4 import java.net.Socket;
5 import java.net.ServerSocket;
6
7 /**
8 * 服务器断的工作就是在指定的端口上监听
9 * <li>建立连接</li>
10 * <li>打开输出流</li>
11 * <li>封装输出流</li>
12 * <li>向客户端发送数据</li>
13 * <li>关闭打开的输出流</li>
14 * <li>关闭打开的socket对象</li>
15 *
16 * @author Hongten
17 *
18 * @time 2012-4-29 2012
19 */
20 public class TestServer {
21 public static void main(String args[]) {
22 try {
23 // 指定服务器端的端口号为8888
24 ServerSocket s = new ServerSocket(8888);
25 while (true) {
26 // 建立连接
27 Socket socket = s.accept();
28 // 打开输出流
29 OutputStream os = socket.getOutputStream();
30 // 封装输出流
31 DataOutputStream dos = new DataOutputStream(os);
32 // s<li>.getInetAddress()获取远程ip地址,s<li>.getPort()远程客户端的断后好
33 // 向客户端发送数据
34 dos.writeUTF("你好,客户端地址信息: " + socket.getInetAddress()
35 + "\t客户端通信端口号: " + socket.getPort());
36 dos.writeUTF("i'm a server ,my name is hongten!");
37 // 关闭打开的输出流
38 dos.close();
39 // 关闭打开的socket对象
40 socket.close();
41 }// 开始下一此循环
42 } catch (IOException e) {
43 e.printStackTrace();
44 }
45 }
46 }
客户端代码:
1 package com.b510.socket1703;
2
3 import java.io.*;
4 import java.net.Socket;
5
6 /**
7 * 客户端
8 * @author Hongten
9 *
10 * @time 2012-4-29 2012
11 */
12 public class TestClient {
13 public static void main(String args[]) {
14 try {
15 // 创建socket对象,指定服务器的ip地址,和服务器监听的端口号
16 // 客户端在new的时候,就发出了连接请求,服务器端就会进行处理,如果服务器端没有开启服务,那么
17 // 这时候就会找不到服务器,并同时抛出异常==》java.net.ConnectException: Connection
18 // refused: connect
19 Socket s1 = new Socket("127.0.0.1", 8888);
20 // 打开输入流
21 InputStream is = s1.getInputStream();
22 // 封装输入流
23 DataInputStream dis = new DataInputStream(is);
24 // 打印服务器端发送过来的信息
25 System.out.println(dis.readUTF());
26 System.out.println(dis.readUTF());
27 // 关闭输入流
28 dis.close();
29 // 关闭打开的socket对象
30 s1.close();
31 } catch (IOException e) {
32 e.printStackTrace();
33 }
34 }
35 }
如果服务器端没有打开,这时候运行客户端,出现的结果:
1 java.net.ConnectException: Connection refused: connect
2 at java.net.PlainSocketImpl.socketConnect(Native Method)
3 at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
4 at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
5 at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
6 at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
7 at java.net.Socket.connect(Socket.java:518)
8 at java.net.Socket.connect(Socket.java:468)
9 at java.net.Socket.<init>(Socket.java:365)
10 at java.net.Socket.<init>(Socket.java:179)
11 at com.b510.socket1703.TestClient.main(TestClient.java:19)
如果服务器端先打开服务,这时候客户端连接服务器端,出现的效果:
1 你好,客户端地址信息: /127.0.0.1 客户端通信端口号: 2800
2 i'm a server ,my name is hongten!
============================================================
2.实现单线程的聊天室
============================================================
服务器端代码:
1 package com.b510.socket1704.simplechatroom;
2
3 import java.io.*;
4 import java.net.Socket;
5 import java.net.ServerSocket;
6 import java.net.SocketException;
7
8 /**
9 * 服务器端程序,在while循环中所执行的动作是:
10 * 听,说,听,说,听,说...
11 *
12 * @author Hongten
13 *
14 * @time 2012-4-29 2012
15 */
16 public class TestServer {
17 public static void main(String args[]) {
18 try {
19 //创建一个socket对象
20 ServerSocket s = new ServerSocket(8888);
21 //socket对象调用accept方法,等待连接请求
22 Socket s1 = s.accept();
23 //打开输出流
24 OutputStream os = s1.getOutputStream();
25 //封装输出流
26 DataOutputStream dos = new DataOutputStream(os);
27 //打开输入流
28 InputStream is = s1.getInputStream();
29 //封装输入流
30 DataInputStream dis = new DataInputStream(is);
31 //读取键盘输入流
32 InputStreamReader isr = new InputStreamReader(System.in);
33 //封装键盘输入流
34 BufferedReader br = new BufferedReader(isr);
35
36 String info;
37 while (true) {
38 //接受客户端发送过来的信息
39 info = dis.readUTF();
40 //打印接受的信息
41 System.out.println("对方说: " + info);
42 //如果发现接受的信息为:bye,那么就结束对话
43 if (info.equals("bye"))
44 break;
45 //读取键盘的输入流
46 info = br.readLine();
47 //写入到网络连接的另一边,即客户端
48 dos.writeUTF(info);
49 //如果服务器自己说:bye,也是结束对话
50 if (info.equals("bye"))
51 break;
52 }
53 //关闭输入流
54 dis.close();
55 //关闭输出流
56 dos.close();
57 //关闭socket对象
58 s1.close();
59 s.close();
60 } catch (SocketException e) {
61 System.out.println("网络连接异常,程序退出!");
62 } catch (IOException e) {
63 e.printStackTrace();
64 }
65 }
66 }
客户端代码:
1 package com.b510.socket1704.simplechatroom;
2
3 import java.io.*;
4 import java.net.Socket;
5 import java.net.SocketException;
6 /**
7 * 客户端程序,在while循环中所执行的动作是:
8 * 说,听,说,听,说,听....
9 * @author Hongten
10 *
11 * @time 2012-4-29 2012
12 */
13 public class TestClient {
14 public static void main(String args[]) {
15 try {
16 // 创建socket对象,指定服务器的ip地址,和服务器监听的端口号
17 // 客户端在new的时候,就发出了连接请求,服务器端就会进行处理,如果服务器端没有开启服务,那么
18 // 这时候就会找不到服务器,并同时抛出异常==》java.net.ConnectException: Connection
19 // refused: connect
20 Socket s1 = new Socket("localhost", 8888);
21 //打开输出流
22 OutputStream os = s1.getOutputStream();
23 //封装输出流
24 DataOutputStream dos = new DataOutputStream(os);
25 //打开输入流
26 InputStream is = s1.getInputStream();
27 //封装输入流
28 DataInputStream dis = new DataInputStream(is);
29 //读取键盘输入流
30 InputStreamReader isr = new InputStreamReader(System.in);
31 //封装键盘输入流
32 BufferedReader br = new BufferedReader(isr);
33
34 String info;
35 while (true) {
36 //客户端先读取键盘输入信息
37 info = br.readLine();
38 //把他写入到服务器方
39 dos.writeUTF(info);
40 //如果客户端自己说:bye,即结束对话
41 if (info.equals("bye"))
42 break;
43 //接受服务器端信息
44 info = dis.readUTF();
45 //打印
46 System.out.println("对方说: " + info);
47 if (info.equals("bye"))
48 break;
49 }
50 //关闭相应的输入流,输出流,socket对象
51 dis.close();
52 dos.close();
53 s1.close();
54 } catch (IOException e) {
55 e.printStackTrace();
56 }
57 }
58 }
运行效果:
服务器端效果>>>
1 对方说: hell
2 你好
3 对方说: 嘿嘿
4 你今天
5 对方说: 13
6 代售点
客户端端效果>>>
1 hell
2 对方说: 你好
3 嘿嘿
4 对方说: 你今�?
5 13
6 对方说: 代售�?
当前的程序不管是服务器端,还是客户端,都是单线程的。如: 服务器端说:"你好"
1 //读取键盘的输入流
2 info = br.readLine();
3 //写入到网络连接的另一边,即客户端
4 dos.writeUTF(info);
5 //如果服务器自己说:bye,也是结束对话
通过上面的代码,把"你好"发送出去了,这时候,程序又开始循环,运行到:
1 //接受客户端发送过来的信息
2 info = dis.readUTF();
这段代码,其实在这里就阻塞在这里了。要等到客户端那边说了话,"嘿嘿",这时候这里的
阻塞才会变为非阻塞状态,然后又继续说,说完后又继续阻塞......
而对于客户端来说,其实是一样的道理,客户端说完"hello"后,进入:
1 //接受服务器端信息
2 info = dis.readUTF();
到收听服务器端的信息,在这里也产生了阻塞,只有服务器端说了"你好",这个阻塞才变为非阻塞
状态。然后又继续接下来的动作....
============================================================
3.实现多线程的聊天室
============================================================
服务器端代码:
1 package com.b510.socket1705.freeechatroom;
2
3 import java.io.*;
4 import java.net.*;
5
6 /**
7 * 服务器端程序
8 *
9 * @author Hongten
10 *
11 * @time 2012-4-29 2012
12 */
13 public class TestServer {
14 public static void main(String args[]) {
15 try {
16 // 创建一个socket对象
17 ServerSocket s = new ServerSocket(8888);
18 // socket对象调用accept方法,等待连接请求
19 Socket s1 = s.accept();
20
21 // =========服务器端,在这里应该先打开输出流,在打开输入流,
22 // =========因为服务器端执行的操作是先听,再说,听,说,听,说.....
23
24 // 打开输出流
25 OutputStream os = s1.getOutputStream();
26 // 封装输出流
27 DataOutputStream dos = new DataOutputStream(os);
28 // 打开输入流
29 InputStream is = s1.getInputStream();
30 // 封装输入流
31 DataInputStream dis = new DataInputStream(is);
32 // 创建并启用两个线程
33 new MyServerReader(dis).start();
34 new MyServerWriter(dos).start();
35 } catch (IOException e) {
36 e.printStackTrace();
37 }
38 }
39 }
40
41 // 接受并打印客户端传过来的信息
42 class MyServerReader extends Thread {
43 private DataInputStream dis;
44
45 public MyServerReader(DataInputStream dis) {
46 this.dis = dis;
47 }
48
49 public void run() {
50 String info;
51 try {
52 while (true) {
53 // 如果对方,即客户端没有说话,那么就会阻塞到这里,
54 // 这里的阻塞并不会影响到其他线程
55 info = dis.readUTF();
56 // 如果状态有阻塞变为非阻塞,那么就打印接受到的信息
57 System.out.println("对方说: " + info);
58 if (info.equals("bye")) {
59 System.out.println("对方下线,程序退出!");
60 System.exit(0);
61 }
62 }
63 } catch (IOException e) {
64 e.printStackTrace();
65 }
66 }
67 }
68
69 // 从键盘获得输入流并写入信息到客户端
70 class MyServerWriter extends Thread {
71 private DataOutputStream dos;
72
73 public MyServerWriter(DataOutputStream dos) {
74 this.dos = dos;
75 }
76
77 public void run() {
78 // 读取键盘输入流
79 InputStreamReader isr = new InputStreamReader(System.in);
80 // 封装键盘输入流
81 BufferedReader br = new BufferedReader(isr);
82 String info;
83 try {
84 while (true) {
85 info = br.readLine();
86 dos.writeUTF(info);
87 if (info.equals("bye")) {
88 System.out.println("自己下线,程序退出!");
89 System.exit(0);
90 }
91 }
92 } catch (IOException e) {
93 e.printStackTrace();
94 }
95 }
96 }
客户端代码:
1 package com.b510.socket1705.freeechatroom;
2
3 import java.io.*;
4 import java.net.*;
5
6 /**
7 * 客户端程序
8 *
9 * @author Hongten
10 *
11 * @time 2012-4-29 2012
12 */
13 public class TestClient {
14 public static void main(String args[]) {
15 try {
16 // 创建socket对象,指定服务器的ip地址,和服务器监听的端口号
17 // 客户端在new的时候,就发出了连接请求,服务器端就会进行处理,如果服务器端没有开启服务,那么
18 // 这时候就会找不到服务器,并同时抛出异常==》java.net.ConnectException: Connection
19 // refused: connect
20 Socket s1 = new Socket("127.0.0.1", 8888);
21
22 // =========客户端,在这里应该先打开输入流,在打开输出流,
23 // =========因为客户端执行的操作是先说,再听,说,听,说,听.....
24
25 // 打开输入流
26 InputStream is = s1.getInputStream();
27 // 封装输入流
28 DataInputStream dis = new DataInputStream(is);
29 // 打开输出流
30 OutputStream os = s1.getOutputStream();
31 // 封装输出流
32 DataOutputStream dos = new DataOutputStream(os);
33
34 // 创建并启用两个线程
35 new MyClientReader(dis).start();
36 new MyClientWriter(dos).start();
37 } catch (IOException e) {
38 e.printStackTrace();
39 }
40 }
41 }
42
43 // 接受并打印服务器端传过来的信息
44 class MyClientReader extends Thread {
45 private DataInputStream dis;
46
47 public MyClientReader(DataInputStream dis) {
48 this.dis = dis;
49 }
50
51 public void run() {
52 String info;
53 try {
54 while (true) {
55 info = dis.readUTF();
56 System.out.println("对方说: " + info);
57 if (info.equals("bye")) {
58 System.out.println("对方下线,程序退出!");
59 System.exit(0);
60 }
61 }
62 } catch (IOException e) {
63 e.printStackTrace();
64 }
65 }
66 }
67
68 // 从键盘获得输入流并写入信息到服务器端
69 class MyClientWriter extends Thread {
70 private DataOutputStream dos;
71
72 public MyClientWriter(DataOutputStream dos) {
73 this.dos = dos;
74 }
75
76 public void run() {
77 InputStreamReader isr = new InputStreamReader(System.in);
78 BufferedReader br = new BufferedReader(isr);
79 String info;
80 try {
81 while (true) {
82 info = br.readLine();
83 dos.writeUTF(info);
84 if (info.equals("bye")) {
85 System.out.println("自己下线,程序退出!");
86 System.exit(0);
87 }
88 }
89 } catch (IOException e) {
90 e.printStackTrace();
91 }
92 }
93 }
客户端运行效果:
1 这是客户端
2 我是hongten
3 这是我说的第三句话,haha
4 对方说: 我是服务器端,这说我说的第一句话,hehe
服务器端运行效果:
1 对方说: 这是客户�?
2 对方说: 我是hongten
3 对方说: 这是我说的第三句话,haha
4 我是服务器端,这说我说的第一句话,hehe