Socket是TCP/IP协议上的一种通信,在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路。一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信。
Client A 发信息给 Client B , A的信息首先发送信息到服务器Server ,Server接受到信息后再把A的信息广播发送给所有的Clients
首先我们要在服务器建立一个ServerSocket ,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状态。
Socket accept():如果接收到一个客户端Socket的连接请求,该方法将返回一个与客户端Socket对应的Socket
Server示例:
//创建一个ServerSocket,用于监听客户端Socket的连接请求
ServerSocket ss = new ServerSocket(30000);
//采用循环不断接受来自客户端的请求
while (true){
//每当接受到客户端Socket的请求,服务器端也对应产生一个Socket
Socket s = ss.accept();
//下面就可以使用Socket进行通信了
...
}
客户端通常可使用Socket的构造器来连接到指定服务器
Client示例:
//创建连接到服务器、30000端口的Socket
Socket s = new Socket("192.168.2.214" , 30000);
//下面就可以使用Socket进行通信了
...
这样Server和Client就可以进行一个简单的通信了
当然,我们要做的是多客户,所以每当客户端Socket连接到该ServerSocket之后,程序将对应Socket加入clients集合中保存,并为该Socket启动一条线程,该线程负责处理该Socket所有的通信任务
//定义保存所有Socket的ArrayList
public static ArrayList<Socket> clients = new ArrayList<Socket>();
当服务器线程读到客户端数据之后,程序遍历clients集合,并将该数据向clients集合中的每个Socket发送一次。这样就可以实现一个聊天室的功能了
下面来看看整个功能的demo
先建立一个Java工程,把Server.java运行起来,然后再运行手机模拟器
服务器打印信息:
程序文件结构:
嘿嘿,大家别笑我,我的JAVA水平还是初学者,很多地方都觉得很菜,代码规格程度:小学。 有待提高啊!
1.先看看主Activity : SocketmsgActivity.java
SocketmsgActivity.java
2.初始化IP和端口Activity, IniActivity.java
IniActivity.java
3.初始化用户名称Activity, IniuserActivity.java
IniuserActivity.java
4.config.java
config.java
布局文件:
1.main.xml
main.xml
2.config.xml
config.xml
3.configuer.xml
configuser.xml
style文件:dimens.xml
dimens.xml
最后是服务器文件:Server.java
1 import java.io.*;
2 import java.net.*;
3 import java.text.DateFormat;
4 import java.text.SimpleDateFormat;
5 import java.util.*;
6
7 import javax.sound.sampled.Port;
8 import javax.swing.JOptionPane;
9
10 public class Server {
11
12 ServerSocket ss = null;
13 private String getnameString=null;
14 boolean started = false;
15 List<Client> clients = new ArrayList<Client>();
16 List<Info> infos = new ArrayList<Info>();
17 public static void main(String[] args) {
18 String inputport = JOptionPane.showInputDialog("請輸入該服務器使用的端口:");
19 int port = Integer.parseInt(inputport);
20 new Server().start(port);
21 }
22
23 public void start(int port) {
24 try {
25 ss = new ServerSocket(port);
26 System.out.println("服務器啟動");
27 started = true;
28 } catch (BindException e) {
29 System.out.println(" 端口已经被占用");
30 System.exit(0);
31 }
32 catch (IOException e) {
33 e.printStackTrace();
34 }
35
36 try {
37 while (started) {
38 Socket s = ss.accept();
39 Client c = new Client (s);
40 System.out.println("a client is connected");
41 new Thread(c).start();
42 clients.add(c);
43
44
45 }
46 } catch (IOException e) {
47 e.printStackTrace();
48 }
49 finally {
50 try {
51 ss.close();
52 } catch (IOException e) {
53 e.printStackTrace();
54 }
55 }
56 }
57 public List<Client> getClient(){
58 return clients;
59 }
60
61 class Client implements Runnable {
62 private String chatKey="SLEEKNETGEOCK4stsjeS";
63 private Socket s = null;
64 private DataInputStream dis = null;
65 private DataOutputStream dos = null;
66 private boolean bConnected = false;
67 private String sendmsg=null;
68 Client (Socket s) {
69 this.s = s;
70 try {
71 dis = new DataInputStream (s.getInputStream());
72 dos = new DataOutputStream (s.getOutputStream());
73 bConnected = true;
74 } catch(IOException e) {
75 e.printStackTrace();
76 }
77 }
78
79 public void send (String str) {
80
81 try {
82 //System.out.println(s);
83 dos.writeUTF(str+"");
84 dos.flush();
85 } catch(IOException e) {
86 clients.remove(this);
87 System.out.println("对方已经退出了");
88 }
89 }
90 public void run() {
91 try {
92 while (bConnected) {
93 String str = dis.readUTF();
94 DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
95 String date = " ["+df.format(new Date())+"]";
96 if(str.startsWith(chatKey+"online:")){
97 Info info = new Info();
98 getnameString = str.substring(27);
99
100 info.setName(getnameString);
101 infos.add(info);
102 for (int i=0; i<clients.size(); i++) {
103 Client c = clients.get(i);
104 c.send(getnameString+" on line."+date);
105 }
106 System.out.println(getnameString+" on line."+date);
107 }else if(str.startsWith(chatKey+"offline:")){
108 getnameString = str.substring(28);
109 clients.remove(this);
110 for (int i=0; i<clients.size(); i++) {
111 Client c = clients.get(i);
112 c.send(getnameString+" off line."+date);
113 }
114 System.out.println(getnameString+" off line."+date);
115 }
116 else{
117 int charend = str.indexOf("end;");
118 String chatString = str.substring(charend+4);
119 String chatName = str.substring(25, charend);
120
121 sendmsg=chatName+date+"\n"+chatString;
122 for (int i=0; i<clients.size(); i++) {
123 Client c = clients.get(i);
124 c.send(sendmsg);
125 }
126 System.out.println(sendmsg);
127 }
128 }
129 } catch (SocketException e) {
130 System.out.println("client is closed!");
131 clients.remove(this);
132 } catch (EOFException e) {
133 System.out.println("client is closed!");
134 clients.remove(this);
135 }
136 catch (IOException e) {
137 e.printStackTrace();
138 }
139 finally {
140 try {
141 if (dis != null) dis.close();
142 if (dos != null) dos.close();
143 if (s != null) s.close();
144 } catch (IOException e) {
145 e.printStackTrace();
146 }
147 }
148 }
149 }
150
151 class Info{
152 private String info_name = null;
153 public Info(){
154
155 }
156 public void setName(String name){
157 info_name = name;
158 }
159 public String getName(){
160 return info_name;
161 }
162 }
163 }
以上只是一个粗略的聊天室功能,如果要实现私聊,还需要保存该Socket关联的客户信息。一个客户端可以将信息发送另一个指定客户端。实际上,我们知道所有客户端只与服务器连接,客户端之间并没有互相连接。这个功能等我以后有时间再写个demo.....