服务端使用的是Tomcat9的example提供的例子。Tomcat7 开始支持Websocket协议,最初是使用两种方式可以实现Websocket的服务端 ,一个是WebSocketServlet,另一个是通过注解。在Tomcat9中废除了使用WebsocketServlet的方法,所以在这里使用注解的方法。今天只是来做个雏形,只要把example拿来用就好。贴上服务端代码:
package websocket.chat;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value = "/websocket/chat")
public class ChatAnnotation {
private static final String GUEST_PREFIX = "Guest";
private static final AtomicInteger connectionIds = new AtomicInteger(0);
private static final Set<ChatAnnotation> connections =
new CopyOnWriteArraySet<>();
private final String nickname;
private Session session;
public ChatAnnotation() {
nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
}
@OnOpen
public void start(Session session) {
this.session = session;
connections.add(this);
String message = String.format("* %s %s", nickname, "has joined.");
broadcast(message);
}
@OnClose
public void end() {
connections.remove(this);
String message = String.format("* %s %s",
nickname, "has disconnected.");
broadcast(message);
}
@OnMessage
public void incoming(String message) {
// Never trust the client
String filteredMessage = String.format("%s: %s",
nickname, message.toString());
broadcast(filteredMessage);
}
@OnError
public void onError(Throwable t) throws Throwable {
}
private static void broadcast(String msg) {
for (ChatAnnotation client : connections) {
try {
synchronized (client) {
client.session.getBasicRemote().sendText(msg);
}
} catch (IOException e) {
connections.remove(client);
try {
client.session.close();
} catch (IOException e1) {
// Ignore
}
String message = String.format("* %s %s",
client.nickname, "has been disconnected.");
broadcast(message);
}
}
}
}
Tomcat的客户端例子是一个html网页,我们需要自己在Android客户端上实现。标题已经说了 使用Okhttp,简单熟悉一下API,找到OkhttpClient的关于websocket的方法拿来用就好。客户端代码也比较简单。
package jiacc.demo.websocket;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
public class MainActivity extends AppCompatActivity {
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView)findViewById(R.id.tv);
}
public void onClick(View view){
OkHttpClient okHttpClient=new OkHttpClient();
Request request=new Request.Builder().url("ws://192.168.1.106:8080/websocket/websocket/chat").build();
okHttpClient.newWebSocket(request,new Listener());
}
private class Listener extends WebSocketListener{
@Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
}
@Override
public void onMessage(WebSocket webSocket,final String text) {
super.onMessage(webSocket, text);
runOnUiThread(new Runnable() {
@Override
public void run() {
tv.append("\n"+text);
}
});
}
@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
super.onClosed(webSocket, code, reason);
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
}
}
}
部署运行Tomcat服务端,运行客户端,就可了。如何两个手机运行客户端太麻烦,可以用网页和Android端进行通信。
如此,我们利用Tomcat和Okhttp两个现成的轮子,就把一个聊天系统的雏形搭成了。太简单了有没有!!!!
当然,这只是万里长征的第一步,相比于企业级的应用,这连个玩具都算不上。后续通过对服务端和客户端逻辑的修改,希望能把它做成一个功能完善,可用性强,安全,便捷的系统。
今年的重点就是跟网络刚,学习网络没有个服务端技术是不行的,tomcat7之后支持websocket协议。初步构想是,实现一个服务端使用Tomcat ,客户端使用Okhttp的websocket聊天框架。当对http有一定的熟悉之后,websocket学习起来也是相对容易的。之所以想把它写出来,是因为最近一年的时间学习了不少网络编程的东西,但是零零碎碎没有成为一个系统,所以当下的想法是写一个相对完整的东西,把零碎的东西整合起来。