下面将基于TCP协议用JAVA写一个非常简单的聊天室程序, 聊天室具有以下功能,

  • 在服务器端,可以接受客户端注册(用户名),可以显示注册成功的账户
  • 在客户端,可以注册一个账号,并用这个账号发送信息
  • 发送信息有两种模式,一种是群聊,所有在线用户都可以看到消息,另一种是私聊,只针对指定账户发送消息

下面是主要的实现思路,

  1. 首先是服务器端, 需要使用多线程实现。 主线程用来循环监听客户端的连接请求, 一旦接收到一个请求,就为这个客户端创建一个专用通信线程。
  2. 服务器端依靠一个经过重写的map保存在线的客户端账户以及建立连接后的通信句柄(inputStream/outputStream)
  3. 服务器端和客户端通信使用约定好的自定义协议,将在双方发送的消息中添加固定消息头和消息尾。 通信双发都使用socket的inputStream和outStream读和写消息,与本地IO区别不大。
  4. 当服务器端接收到客户端的请求的时候,先解析出消息头和尾,根据约定的通信协议来判断消息类型,是注册账户,还是群发消息,还是私聊消息
  5. 对于群发消息,服务器端将遍历在线的所有用户(线程),然后将消息广播出去
  6. 对于私聊消息,服务器端根据客户端发来的目的地址(收信账户),去map中查找到通信线程句柄(outputStream),然后将信息发送给指定账户
  7. 对于每个客户端,都创建两个线程。 主线程用来做键盘输入, 辅线程用来接收服务器发回的消息
  8. 客户端的主线程中,所有消息都是先发送到服务器端,再由服务器端决定分发策略。
  9. 包括注册账户在内,服务器和客户端双方所有消息都是经过约定协议包装过的,这样服务器才能读取消息的属性,进行指定操作。

服务器端实现如下,

首先我们要自定义一个通信协议,服务器端和客户端需要使用同一种协议,用来描述消息的属性,

 package chat;

 public interface ChatProtocol {
int PROTOCOL_LEN = 2; //协议字符串,会加入数据包中
String MSG_ROND = "##";
String USER_ROND = "@@";
String LOGIN_SUCCESS = "1";
String NAME_REP = "-1";
String PRIVATE_ROND = "%%";
String SPLIT_SIGN = "}"; }

服务器端的监听线程(主线程)

 package chat;

 import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket; public class Server {
private static final int SERVER_PORT = 33000;
public static ChatMap<String, PrintStream> clients = new ChatMap();
public void init() {
try {
ServerSocket ss = new ServerSocket(SERVER_PORT) ;
while(true) {
Socket socket = ss.accept();
new ServerThread(socket).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server = new Server();
server.init();
}
}

服务器端需要使用一个重写的map来存放用户名和对应的通信句柄, 这样才能实现私聊功能,

 package chat;

 import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set; //用map来保存用户和socket输出流的对应关系,
//K将会是String类型的用户名,不允许重复
//V是从socket返回的outputStream对象,也不允许重复
public class ChatMap<K,V> {
public Map<K,V> map = Collections.synchronizedMap(new HashMap<K,V>()); //根据outputStream对象删除制定项
public synchronized void removeByValue(Object value) {
for (Object key : map.keySet()) {
if(map.get(key) == value) {
map.remove(key);
break;
}
}
} //获取outputStream对象组成的Set
public synchronized Set<V> valueSet() {
Set<V> result = new HashSet<V>();
//遍历map,将map的value存入Set
for(K key : map.keySet()) {
result.add(map.get(key));
}
/*
for (Map.Entry<K, V> entry : map.entrySet()) {
result.add(entry.getValue());
}
*/
return result;
} //根据ouputStream对象查找用户名
public synchronized K getKeyByValue(V val) {
for(K key : map.keySet()) {
if (map.get(key) == val || map.get(key).equals(val)) {
return key;
}
}
return null;
} //实现put,key和value都不允许重复
public synchronized V put(K key, V value) {
for (V val : valueSet() ) {
if (val.equals(value) && val.hashCode() == value.hashCode()) {
throw new RuntimeException("此输入流已经被使用");
}
}
return map.put(key, value);
}
}

对每一个客户端请求创建一个通信子线程

 package chat;

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket; public class ServerThread extends Thread{
private Socket socket;
BufferedReader br = null;
PrintStream ps = null; public ServerThread(Socket socket) {
this.socket = socket;
} public void run() {
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//一个客户端的输出流对象
ps = new PrintStream(socket.getOutputStream());
String line = null;
while((line = br.readLine()) != null) {
//如果消息以ChatProtocol.USER_ROND开始,并以其结束
//则可以确定读到的是用户登录的用户名
if(line.startsWith(ChatProtocol.USER_ROND) &&
line.endsWith(ChatProtocol.USER_ROND)) {
String userName = getRealMsg(line);
//用户名不允许重复
if(Server.clients.map.containsKey(userName)) {
System.out.println("用户名重复");
ps.println(ChatProtocol.NAME_REP);
} else {
System.out.println("["+userName+"] 注册成功,你可以开始聊天了!");
ps.println(ChatProtocol.LOGIN_SUCCESS);
//将用户名和输出流对象组成的键值关联对存入前面经过改造的map
Server.clients.map.put(userName, ps);
}
} //如果消息以ChatProtocol.PRIVATE_ROND开头并以ChatProtocol.PRIVATE_ROND结尾
//则可以确定是私聊信息
else if (line.startsWith(ChatProtocol.PRIVATE_ROND ) &&
line.endsWith(ChatProtocol.PRIVATE_ROND)) {
String userAndMsg = getRealMsg(line); //以SPILT_SIGN分割字符串,前半是用户名,后半是聊天信息
String user = userAndMsg.split(ChatProtocol.SPLIT_SIGN)[0];
String msg = userAndMsg.split(ChatProtocol.SPLIT_SIGN)[1];
//根据用户名在map中找出输出流对象,进行私聊信息发送
Server.clients.map.get(user).println("[私聊信息] [来自 "+Server.clients.getKeyByValue(ps)+"] : " + msg); }
// 群聊信息,广播消息
else {
String msg = getRealMsg(line);
for(PrintStream clientPs : Server.clients.valueSet()) {
clientPs.println("[群发信息] [来自 "+Server.clients.getKeyByValue(ps)+"] : " + msg);
}
}
}
} catch (IOException e) {
//e.printStackTrace();
Server.clients.removeByValue(ps);
System.out.println(Server.clients.map.size());
try {
if (br != null) {
br.close();
} if (ps != null) {
ps.close();
} if (socket != null) {
socket.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
} private String getRealMsg(String line) {
return line.substring(ChatProtocol.PROTOCOL_LEN, line.length() - ChatProtocol.PROTOCOL_LEN);
} }

下面开始写客户端, 客户端和服务器端是两个完全独立的应用, 可以新建工程写一个客户端,

为了简单起见,我将服务器端和客户端放在了同一个工程的同一个包下, 这样可以共享一下协议接口 ChatProtocol.java

首先是客户端主程序,用来完成键盘输入操作, 其中注册用户名的地方调用了一点点java的gui编程接口swi,弹出对话框输入用户名,

 package chat;

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket; import javax.swing.JOptionPane; public class Client {
private static final int SERVER_PORT = 33000;
private Socket socket;
private PrintStream ps;
private BufferedReader brServer;
private BufferedReader keyIn; public void init() {
try {
keyIn = new BufferedReader(new InputStreamReader(System.in));
socket = new Socket("127.0.0.1", SERVER_PORT);
ps = new PrintStream(socket.getOutputStream());
brServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String tip = "";
while(true) {
String userName = JOptionPane.showInputDialog(tip + "输入用户名");
ps.println(ChatProtocol.USER_ROND + userName + ChatProtocol.USER_ROND); //服务器端响应
String result = brServer.readLine();
if(result.equals(ChatProtocol.NAME_REP)) {
tip = "用户名重复,请重新输入";
continue;
}
//登录成功
if(result.equals(ChatProtocol.LOGIN_SUCCESS)) {
System.out.println("登录成功,账号: ["+ userName +"]");
break;
}
}
} catch (IOException ex) {
ex.printStackTrace();
} new ClientThread(brServer).start();
} private void readAndSend() {
try {
String line = null;
while((line = keyIn.readLine()) != null) {
//如果发送的消息中带有冒号,且以//开头,则认为是私聊信息
if(line.indexOf(":") > 0 && line.startsWith("//")) {
line = line.substring(2);
ps.println(ChatProtocol.PRIVATE_ROND
+ line.split(":")[0]
+ ChatProtocol.SPLIT_SIGN
+ line.split(":")[1]
+ ChatProtocol.PRIVATE_ROND);
} else {
ps.println(ChatProtocol.MSG_ROND + line + ChatProtocol.MSG_ROND);
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
} private void closeRs() {
try {
if (keyIn != null) {
keyIn.close();
} if (brServer != null) {
brServer.close();
} if (ps != null) {
ps.close();
} if (socket != null) {
socket.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
} public static void main(String[] args) {
Client client = new Client();
client.init();
client.readAndSend();
}
}

键盘操作中,区分群发消息和私聊消息是看消息以什么开头,以//开头就是私聊,否则是群发,

私聊时,用冒号隔开收信人和消息内容, 一条私聊消息格式是这样的    //b:hi, i'm a

下面是客户端的子线程,专门用来回显服务器端发回来的消息,

 package chat;

 import java.io.BufferedReader;
import java.io.IOException; public class ClientThread extends Thread { BufferedReader br = null; public ClientThread(BufferedReader brServer) {
this.br = brServer;
} public void run() {
try {
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} }

下面是执行结果, 先启动一个Server端的进程,可以看到启动之后Server端处于监听阻塞状态,

接着分别启动两个Client端进程,每次启动Client进程的时候都会要求输入用户名,要保证用户名不能重复,

接着就可以发送消息了,普通消息将会发送给所有人,即群发, 指定格式的消息将是私聊,例如 //bbb:hi I'm aaa     (这是发给账户bbb)的私人消息。

aaarticlea/png;base64,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jnr26456zuuOes7rjn7O649+zuuPfu7rj37uXx/93L8+5nnG3nDM895w7B+/4dg/3tXY8ufvuvz5b9xuf/KmFcZe8KYVL3jzccZe+ObjXviW4174luNf+Jbj//Stxk7407ee8Gd/Y+zEF73tZ/bivz1pu739pD9/+8nb7R0nv+QdJ7/kHae85J2nvOSdp7z0nae89J2nvvTvTn2ZsXed9rJ3nbbM2LtPW/bulS9/98qXv8fY6a94z+mveO/pr3jv6a987+mvfO8Zr3zfGa983xmvet8Zr3r/mcZe/f4zX73bWcb+4gPGzv7LD5z9lx80ds5ffai2c1/z4R22+7mv3f287faR83b5yPm7fOT8XT56/uu22wWv+/sLXr/dvvD6j33hr419/MK//viFbzC2x4W77nHRrntctOueF+2650Vv3PPiN+558Rv3uviNe138pr0uftPelxh7896XvHmfL755ny++ZZ8vvmXfL75l3y+9Zd8vvXXfL731E8Yu/ZtP1nbZ2/b7mf3tpy439vZPX/72T19h7B2fueIdn7nyHZ+58h3/cOU7t9uX3/nZL/+dsc9d9a7a9v/Ku40d8JV3H/CV9xxw9XsOuPo9B179ngOvfu+B17x34Zr3LlzzPmMHXfu+g659/0HXvv/ga99/8HXvP/i63Q6+brdDrtvtkK/udshXP3DIVz9wqLGvffCw7fahw67/0OHb7cOfv/7Dn/+6sd2P+PruR9yw+xE37H7kDR858oaPHPmNjxz5jY8etcOO/ubf13bMjR8zduyNHzv2po8bW37THstv2mP5aI/loz1WjPZcMdpzxbf2PO5bex73rb2MHX/zXsffvPfxN+99ws17n3DL3ifcss8Jt+xz4i37nPjtfU/89r4nbbdPnHTrJ07ebp885bba9jv1tv1OvX2/U2//1GnGVn3qtFWfXmnsO58+/Tufqe2MO/5hh332zDu321l3fu6sOz931urPnbX6c2ev3v/s1fuffdf+59y1/zl3HXDOXQecc/cB5959wLl3H3ju3Qeed/eB592zYOz8exbOX3PQ+WsOusDYvQdfcO/BX9huh1x4n7FDL7zv0IvuN3bYRfcfdvH9h108Puzi8eGXGFs8/JLFz3/R2NojvvQzO/LSddvtsnVHXbZ+u12+/ujL1x99+Yajr9hw9BUbjrliwzFXbDzmyo3HGvvy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" alt="" />

JAVA基础知识之网络编程——-基于TCP通信的简单聊天室的更多相关文章

  1. JAVA基础知识之网络编程——-基于UDP协议的通信例子

    UDP是一种不可靠的协议,它在通信两端各建立一个socket,这两个socket不会建立持久的通信连接,只会单方面向对方发送数据,不检查发送结果. java中基于UDP协议的通信使用DatagramS ...

  2. JAVA基础知识之网络编程——-基于AIO的异步Socket通信

    异步IO 下面摘子李刚的<疯狂JAVA讲义> 按照POSIX标准来划分IO,分为同步IO和异步IO.对于IO操作分为两步,1)程序发出IO请求. 2)完成实际的IO操作. 阻塞IO和非阻塞 ...

  3. JAVA基础知识之网络编程——-基于NIO的非阻塞Socket通信

    阻塞IO与非阻塞IO 通常情况下的Socket都是阻塞式的, 程序的输入输出都会让当前线程进入阻塞状态, 因此服务器需要为每一个客户端都创建一个线程. 从JAVA1.4开始引入了NIO API, NI ...

  4. JAVA基础知识之网络编程——-网络基础(Java的http get和post请求,多线程下载)

    本文主要介绍java.net下为网络编程提供的一些基础包,InetAddress代表一个IP协议对象,可以用来获取IP地址,Host name之类的信息.URL和URLConnect可以用来访问web ...

  5. 【转载】[基础知识]【网络编程】TCP/IP

    转自http://mc.dfrobot.com.cn/forum.php?mod=viewthread&tid=27043 [基础知识][网络编程]TCP/IP iooops  胖友们楼主我又 ...

  6. JAVA基础知识之网络编程——-TCP/IP协议,socket通信,服务器客户端通信demo

    OSI模型分层 OSI模型是指国际标准化组织(ISO)提出的开放系统互连参考模型(Open System Interconnection Reference Model,OSI/RM),它将网络分为七 ...

  7. JAVA基础知识之网络编程——-网络通信模型(IO模型)

    <Unix网络编程:卷1>中介绍了5中I/O模型,JAVA作为运行在宿主机上的程序,底层也遵循这5中I/O模型规则.这5中I/O模型分别是: 阻塞式IO 非阻塞式IO I/O复用 信号驱动 ...

  8. JAVA基础知识之网络编程——-使用Proxy创建连接

    在前面的HTTP网络通信的例子中,使用了URLConnection conn = url.openConnection();连接网络, 如果改用URLConnection conn = url.ope ...

  9. JAVA基础知识之网络编程——-使用MutilcastSocket实现多点广播

    IP多点广播原理 设置一组特殊网络地址作为多点广播地址,每一个多点广播地址都被看作一个组,当客户需要发送和接受信息时,加入到该组即可. IP协议为多点广播提供了一批特殊的IP地址,范围是224.0.0 ...

随机推荐

  1. node.js学习(1)

    新建便笺 3 node.js学习(1) 1)安装 http://nodejs.org/download/下载. 2)编写一个案例 var http=require("http"); ...

  2. Xcode 遇到 App Transport Security has blocked a cleartext HTTP 错误

    今天用Xcode  创建新项目用到 URL 发送请求时,报下面的错: “App Transport Security has blocked a cleartext HTTP (http://) re ...

  3. C++Primer 第十九章

    //1.控制内存分配: //A:某些应用程序对内存分配有特殊的需求,因此我们无法将标准内存管理机制直接应用于这些程序.它们常常需要自定义内存分配的细节,比如使用关键字new将对象放置在特定的内存空间中 ...

  4. [转] JVM 调优系列 & 高并发Java系列

    1.JVM调优总结(1):一些概念:http://www.importnew.com/18694.html 2.JVM调优总结(2):基本垃圾回收算法:http://www.importnew.com ...

  5. extjs 常见的小问题

    今天,小白就来总结下extjs的使用的时候的各种小问题或者说是小技巧.希望能够给各位刚接触extjs的朋友一点帮助. 1.当存在store的各种组件的store的autoload属性为false的时候 ...

  6. javaapi中的排序

    有的时候需要对数组里的element进行排序.当然可以自己编写合适的排序方法,但既然java包里有自带的Arrays.sort排序方法,在 数组元素比较少的时候为何不用? Sorting an Arr ...

  7. 认识javascript

    javascript小知识 www.phonegap.com(跨平台开发框架) Cocos2d-Html5(WebGL渲染  javascript语言) creatjs.com(融合了flash动画的 ...

  8. SNMP ber 编码

    5.1 标识域(tag)的编码规则 标识域指明数据的类型,占用1个字节,常见的类型有:BOOL(0x01);INT(0x02);OCTSTR(0x04);NULL(0x05);OBJID(0x06); ...

  9. IMapDocument interface

      Provides access to members that control the reading and writing of map document files.(提供访问的成员,控制读 ...

  10. 基于时间点恢复数据库stopat

    create database newtestdb use newtestdbgo drop table t1go create table t1 (id int not null identity( ...