最近研究了一下socket,以前是直接用的,感觉总不好,后来前辈给我介绍了mina。这个框架已经封装好了socket,非常方便,比起直接用socket来说优越性高点。
下面准备客户端和服务端的例子,以及写好的服务端打包成exe文件,运行在服务器上。
先贴下运行效果:
1、服务端的项目:
使用的开发工具是myeclipse。项目中引用了hibernate3.3,只要用来访问本地的sql server数据库,具体如何配置去连接数据库,等会也会说。
项目结构:
数据库配置图片太多了,不会就看我的文档!!!sql server和hibernate的配置都在这个文档里面,需要请下载 sql server 数据库配置。
要使用mina,必须添加mina-core和slf4j-api.jar 包。
与mina相关的类是:MainServer和ServerHandler这两个类。
ServerHandler类:
package com.org.mina;
import java.util.ArrayList;
import java.util.List;
import org.apache.mina.core.filterchain.IoFilterAdapter;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.org.dao.FileUpdataDao;
import com.org.dao.impl.FileUpdataDaoImpl;
import com.org.entity.FileData;
public class ServerHandler extends IoFilterAdapter implements IoHandler {
private FileUpdataDao impl = new FileUpdataDaoImpl();
private static ServerHandler samplMinaServerHandler = null;
public static ServerHandler getInstances() {
if (null == samplMinaServerHandler) {
samplMinaServerHandler = new ServerHandler();
}
return samplMinaServerHandler;
}
private ServerHandler() {
}
@Override
public void exceptionCaught(IoSession arg0, Throwable arg1)
throws Exception {
System.out.println("exceptionCaught");
}
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
System.out.println("messageReceived");
System.out.println("message->"+(String)message);
}
@Override
public void messageSent(IoSession arg0, Object arg1) throws Exception {
System.out.println("messageSent");
}
@Override
public void sessionClosed(IoSession arg0) throws Exception {
System.out.println("sessionClosed");
}
@Override
public void sessionCreated(IoSession arg0) throws Exception {
System.out.println("sessionCreated");
}
@Override
public void sessionIdle(IoSession arg0, IdleStatus arg1) throws Exception {
System.out.println("sessionIdle");
}
@Override
public void sessionOpened(final IoSession session) throws Exception {
System.out.println("sessionOpened");
//不停访问数据库某个表
// Thread thread = new Thread(new myThread(session));
// thread.start();
session.write("服务端向客户端发送来消息:hello!");
}
public class myThread implements Runnable{
private IoSession session;
public myThread(IoSession session){
this.session = session;
}
@Override
public void run() {
while(true){
try {
String hql = "from FileData";
List datalist = impl.getList(hql);
JSONObject Jsonobject = new JSONObject();
JSONArray JsonArray = new JSONArray();
for(int i = 0;i
package com.org.mina;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.List;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.json.JSONArray;
import org.json.JSONObject;
import com.org.dao.FileUpdataDao;
import com.org.dao.impl.FileUpdataDaoImpl;
import com.org.entity.FileData;
public class MainServer {
private static MainServer mainServer = null;
private SocketAcceptor acceptor = new NioSocketAcceptor();
private DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
private int bindPort = 4000;
public static MainServer getInstances() {
if (null == mainServer) {
mainServer = new MainServer();
}
return mainServer;
}
private MainServer() {
chain.addLast("myChin", new ProtocolCodecFilter(
new ObjectSerializationCodecFactory()));
acceptor.setHandler(ServerHandler.getInstances());
try {
acceptor.bind(new InetSocketAddress(bindPort));
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
MainServer.getInstances();
System.out.println("mainServer!!!!!!!!!!!!!");
}
}
2、客户端的项目
项目结构如图,android客户端所添加的slf4j-android.jar,是这个。
关于mina的类:ClientHandler ,MainClient 和MainActivity类。MainClient 用来测试用,程序入口是MainActivity类。
ClientHandler类:
package com.org.mina;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import android.content.Context;
import android.content.Intent;
public class ClientHandler extends IoHandlerAdapter {
private Context context;
// private static ClientHandler samplMinaClientHandler = null;
/*public static ClientHandler getInstances(Context context) {
if (null == samplMinaClientHandler) {
context = context;
samplMinaClientHandler = new ClientHandler(context);
}
return samplMinaClientHandler;
} */
public ClientHandler(Context context) {
this.context = context;
// samplMinaClientHandler = new ClientHandler(context);
}
public void sessionOpened(IoSession session) throws Exception {
System.out.println("sessionOpened");
}
public void sessionClosed(IoSession session) {
System.out.println("sessionClosed");
}
public void messageReceived(IoSession session, Object message)
throws Exception {
Intent intent = new Intent();
intent.setAction("com.mina.broadcast");
intent.putExtra("message", (String)message);
context.sendBroadcast(intent);
}
public void messageSent(IoSession arg0, Object arg1) throws Exception {
System.out.println("messageSent");
}
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
super.exceptionCaught(session, cause);
}
}
package com.org.mina;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import android.view.Menu;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
public class MainActivity extends Activity{
private ListView listView;
private SimpleAdapter simpleAdapter;
private ArrayList> listItem;
private NioSocketConnector connector = new NioSocketConnector();
private DefaultIoFilterChainBuilder chain = connector.getFilterChain();
/* private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
try {
listItem = new ArrayList>();
JSONObject jsonObject = new JSONObject(msg.obj.toString());
JSONArray jsonArray = jsonObject.getJSONArray("FileData");
for(int i = 0;i map = new HashMap();
map.put("info_no", object.get("info_no"));
map.put("fileName", object.get("File_Type_name"));
map.put("Insert_Operator", object.get("Insert_Operator"));
listItem.add(map);
}
simpleAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
};*/
private BroadcastReceiver PriceReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("com.mina.broadcast"))
{
String msg = intent.getStringExtra("message");
try {
listItem.clear();
JSONObject jsonObject = new JSONObject(msg);
JSONArray jsonArray = jsonObject.getJSONArray("FileData");
for(int i = 0;i map = new HashMap();
map.put("info_no", object.get("info_no"));
map.put("fileName", object.get("File_Type_name"));
map.put("Insert_Operator", object.get("Insert_Operator"));
listItem.add(map);
}
simpleAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
java.lang.System.setProperty("java.net.preferIPv4Stack", "true");
java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
listItem = new ArrayList>();
simpleAdapter = new SimpleAdapter (this,listItem,R.layout.listitem,
new String[]{"info_no","fileName","Insert_Operator"},
new int[]{R.id.textView01,R.id.textView02,R.id.textView03});
listView.setAdapter(simpleAdapter);
new Thread(new Runnable(){
@Override
public void run() {
chain.addLast("myChin", new ProtocolCodecFilter(
new ObjectSerializationCodecFactory()));
ClientHandler clientHandler = new ClientHandler(MainActivity.this);
connector.setHandler(clientHandler);
connector.setConnectTimeout(30);
ConnectFuture cf = connector.connect(new InetSocketAddress("192.168.1.104",4000));
cf.join();
System.out.println("isConnected:"+cf.isConnected());
if(!cf.isConnected())
{
System.out.println("连接服务器失败!!!");
}
else
{
System.out.println("连接成功!!!");
}
}
}).start();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void close() {
Intent i = new Intent();
i.setAction("com.mina.broadcast");
sendBroadcast(i);
finish();
}
@Override
protected void onStart() {
super.onStart();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.mina.broadcast");
registerReceiver(PriceReceiver, intentFilter);
}
@Override
protected void onStop() {
super.onStop();
unregisterReceiver(PriceReceiver);
}
}
要注意配置服务器的端口,客户端的ip和端口,ip就是运行服务端的电脑IP。
先运行服务端Mainserver,再运行客服端的MainActivity,就可以了。
服务端和客户端项目下载地址是:mina项目的下载链接
上面就告一段落。不懂的可以提问!!
还有点问题,当多个客户端访问一个服务端时,要保存生成的session,才能给各个会话发送消息,例如:
Collection
for (IoSession sess : sessions)
{
sess.write(result);
textArea.append("第 "+sess.getId()+" 个会话发送的消息:"+result+"\n");
}
但是这样子的话,服务端很容易崩溃!!!不知道有谁用mina socket写过服务端,至少不会那么容易崩溃的说,有的话请告诉我,谢谢!