简单的Socket 编程 服务端和客户端 (封装)

来源:互联网 发布:知科地方门户网站系统 编辑:程序博客网 时间:2024/05/17 05:58


 由于项目需求有推送的功能,技术总监又不想用第三方极光推送,所以在同事的帮助下搭建了简单的socket通讯。


 首先服务端  java搭建


AndriodService.java


package com.android.net;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;import java.util.ArrayList;import java.util.List;public class AndroidService {// // 定义保存所有的Socket// public static List<Socket> socketList = new ArrayList<Socket>();//// public static void main(String[] args) throws IOException {// ServerSocket server = new ServerSocket(3000);// while (true) {// Socket s = server.accept();// socketList.add(s);// // 每当客户端连接之后启动一条ServerThread线程为该客户端服务// new Thread(new ServiceThreada(s)).start();//// }// }public static void main(String[] args) throws IOException {ServerSocket serivce = new ServerSocket(3000);while (true) {// 等待客户端连接Socket socket = serivce.accept();String ip = socket.getInetAddress().toString();System.out.println(System.currentTimeMillis() + "用户IP:" + ip+ " 链接了 ");new Thread(new AndroidRunable(socket)).start();}}}


AndroidRunable .java


package com.android.net;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.Socket;public class AndroidRunable implements Runnable {Socket socket = null;public AndroidRunable(Socket socket) {this.socket = socket;}public void run() {// 向android客户端输出hello worildString line = null;InputStream input;OutputStream output;String str = "hello world!";try {// 向客户端发送信息output = socket.getOutputStream();input = socket.getInputStream();// BufferedReader bff = new BufferedReader(// new InputStreamReader(input));// output.write(str.getBytes("gbk"));// output.flush(); //半关闭socket// socket.shutdownOutput();// 获取客户端的信息System.out.println(Thread.class.getName());ObjectOutputStream oos=new ObjectOutputStream(output);ObjectInputStream ois = new ObjectInputStream(input);while (true) {Object object = ois.readObject();System.out.println(object);if (object instanceof byte[]) {byte[] buff = (byte[]) object;System.out.print(new String(buff, "gbk"));}oos.writeObject("收到消息");}// 关闭输入输出流// output.close();// bff.close();// input.close();// socket.close();} catch (Exception e) {e.printStackTrace();}}}


   因为推送打开服务端要一直保持在线,所以就不关了,反正项目中的服务端不是你搭,关键在客户端是否正常。



 客户端 Andriod项目


首先我要知道客户端收到服务端信息是什么类型,其次要怎么办,怎么执行。


我这个项目是 服务端发送过来一个json  客户端解析得到要到数据,以广播的形式发送通知。


上代码

import java.net.InetSocketAddress;import java.net.Socket;import java.util.Timer;import java.util.TimerTask;import android.app.Application;import android.os.Bundle;import android.os.Message;import android.util.Log;/** * socket 封装类 * 客户端读流线程 * ClientReadThead clientReadThead; * 客户端流线程 * ClientWriteThread clientWriteThread; * @author onebot * */public class ClientSocket {ClientReadThead clientReadThead;ClientWriteThread clientWriteThread;private static ClientSocket reClient;private ClientSocket() {// TODO Auto-generated constructor stub}private ClientSocket(Application context) {// TODO Auto-generated constructor stubnew MyThread(context).start();}public static ClientSocket reSocket(Application context) {if (reClient != null) {reClient.close();reClient = null;}if (reClient == null) {synchronized (ClientSocket.class.getName()) {if (reClient == null) {reClient = new ClientSocket(context);}}}return reClient;}class MyThread extends Thread {Application context;public MyThread(Application context) {this.context = context;}@Overridepublic void run() {// 定义消息Message msg = new Message();msg.what = 0x11;Bundle bundle = new Bundle();bundle.clear();try {// 连接服务器 并设置连接超时为5秒Socket socket = new Socket();socket.connect(new InetSocketAddress("服务端地址",端口号),5000);clientWriteThread = new ClientWriteThread(socket);clientWriteThread.start();clientReadThead = new ClientReadThead(socket, context);clientReadThead.start();timers();} catch (Exception e) {bundle.putString("msg", "连接异常,再次请求连接");msg.setData(bundle);e.printStackTrace();// 发送消息 修改UI线程中的组件try {sleep(5000);reSocket(context);} catch (Exception e2) {// TODO: handle exception}}}}private void timers() {Timer timer = new Timer();timer.schedule(new TimerTasks(), 1000 * 60, 5 * 1000 * 60);// 获得闹钟管理器// AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);// 设置任务执行计划// am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000 * 60, 5 *// 1000 * 60, sender);//从firstTime才开始执行,每隔5秒再执行}class TimerTasks extends TimerTask {@Overridepublic void run() {// TODO Auto-generated method stub// 位置}}//客户端写消息给服务器(位置消息)public void writeMessage(Object ob) {if (clientWriteThread != null) {clientWriteThread.writeMessage(ob);} else {throw new RuntimeException("you need transfer method reSocket");}}private void close() {// TODO Auto-generated method stubif (clientWriteThread != null) {clientWriteThread.close();clientWriteThread = null;}if (clientReadThead != null) {clientReadThead.close();clientReadThead = null;}System.gc();}//public static void closeGc() {reClient.close();reClient = null;System.gc();}}


ClientReadThead.java


import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.io.Serializable;import java.net.Socket;import android.app.Application;import android.content.Context;import android.content.Intent;import android.util.Log;import android.widget.Toast;/** * 客户端读流线程 * @author onebot * */public class ClientReadThead extends Thread {private Socket socket;private ObjectInputStream ois;private boolean tag = true;private int len = -1;private byte[] b;public Application context;public ClientReadThead(Socket socket, Application context) {// TODO Auto-generated constructor stubtry {this.context = context;this.socket = socket;this.ois = new ObjectInputStream(socket.getInputStream());b = new byte[1024 * 1024 * 5];} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();tag = false;}}@Overridepublic void run() {// TODO Auto-generated method stubsuper.run();try {while (tag) {synchronized (this) {Object ob = ois.readObject();dealMessage(ob);}}close();} catch (Exception e) {// TODO: handle exceptiontag = false;ClientSocket.reSocket(context);e.printStackTrace();}}private void dealMessage(Object ob) {// TODO Auto-generated method stub// 广播Intent intent = new Intent();intent.setAction("com.box");Log.e("=========", "走没走");if (ob instanceof String) {intent.putExtra("msg", ob.toString());} else if (ob instanceof Serializable) {Serializable s = (Serializable) ob;intent.putExtra("msg", s);}context.sendOrderedBroadcast(intent, null); // 有序广播发送// Toast.makeText(context, "发送广播成功", Toast.LENGTH_SHORT).show();System.out.println(ob);} public void close() {try {ois.close();ois = null;} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}


ClientWriteThread .java


import java.io.IOException;import java.io.ObjectOutputStream;import java.net.Socket;/** * 客户端写流线程 */public class ClientWriteThread extends Thread {private boolean tag = true;private final static String TAG = "com.xiao.hei.Thread.WriteThread";private Object o;private Socket socket;private ObjectOutputStream os;public ClientWriteThread(Socket socket) {// TODO Auto-generated constructor stubtry {this.socket = socket;this.os = new ObjectOutputStream(socket.getOutputStream());} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();tag = false;}}@Overridepublic void run() {// TODO Auto-generated method stubsuper.run();try {while (tag) {synchronized (this) {if (o == null)wait();else {os.writeObject(o);o = null;}}}} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}synchronized public void writeMessage(Object o) {System.out.println(o);this.o = o;notify();}public synchronized void close() {try {notify();tag = false;os.close();socket.close();} catch (Exception e) {// TODO: handle exception}}}


广播 SocketReceiver.java


import java.io.Serializable;import android.annotation.SuppressLint;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.support.v4.app.NotificationCompat;import android.support.v4.app.NotificationCompat.Builder;import android.util.Log;import android.widget.RemoteViews;public class ClientReceiver extends BroadcastReceiver {public static final String LOGIN_BOX = "com.box";public static final String LOGIN_USER = "";public static final String LOGIN_LOACTION = "";public static final String MSG_SERVICE = "";/** Notification构造器 */NotificationCompat.Builder mBuilder;/** Notification的ID */int notifyId = 100;/** Notification管理 */public NotificationManager mNotificationManager;public Context context;public PushBean push;public String MsgContent;public int MsgType;public String MsgImgpath;@SuppressLint("NewApi")@Overridepublic void onReceive(Context context, Intent intent) {// TODO Auto-generated method stub// String action = intent.getAction();System.out.println("接受到广播");this.context = context;initNotify();mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);// 获取系统通知的服务push = new PushBean();Object msg = intent.getExtras().get("msg");Log.e(ClientReceiver.class.getName(), msg.toString());if (msg instanceof String) {deal_string(msg.toString());} else if (msg instanceof Serializable) {deal_serializable((Serializable) msg);}}private void deal_serializable(Serializable serializable) {// showIntentActivityNotify(serializable.toString());shwoNotify(serializable.toString());System.out.println("11111");}// / {"type":1,"msg":{}} type 类型 0 1 2 3 4 5 6private void deal_string(String string) {//try {//JSONObject jo = new JSONObject(string);//PushBean push = new PushBean();//push.setContent(jo.getString("content"));////push.setType(jo.getInt("type"));//push.setImg_path(jo.getString("img"));//////MsgContent = push.getContent();//MsgType=push.getType();//MsgImgpath=push.getImg_path();////if(MsgType==1){////类型1的通知////}//if(MsgType==2){////发送登录后的类型2的通知////}//if(MsgType==3){////发送附件有网吧的类型3的通知////{//shwoNotify(string);}//} catch (JSONException e) {//// TODO Auto-generated catch block//e.printStackTrace();//}//// showIntentActivityNotify(string);//}public PendingIntent getDefalutIntent(int flags) {PendingIntent pendingIntent = PendingIntent.getActivity(context, 1,new Intent(), flags);return pendingIntent;}public void showIntentActivityNotify(String text) {// Notification.FLAG_ONGOING_EVENT --设置常驻// Flag;Notification.FLAG_AUTO_CANCEL 通知栏上点击此通知后自动清除此通知// notification.flags = Notification.FLAG_AUTO_CANCEL;// //在通知栏上点击此通知后自动清除此通知try {// mBuilder = new NotificationCompat.Builder(context);mBuilder.setAutoCancel(true)// 点击后让通知将消失.setContentTitle("奇葩葩").setContentText(text).setSmallIcon(R.drawable.ico_qpp).setTicker("有新的更新");// 点击的意图ACTION是跳转到IntentIntent resultIntent = new Intent(context, MainActivity.class);resultIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);mBuilder.setContentIntent(pendingIntent);mNotificationManager.notify(notifyId, mBuilder.build());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}/** * 初始化通知栏 * */private void initNotify() {mBuilder = new NotificationCompat.Builder(context);mBuilder.setContentTitle("<span style="font-family: Arial, Helvetica, sans-serif;">QPP</span>").setContentText("<span style="font-family: Arial, Helvetica, sans-serif;">QPP</span>有新的更新")
.setContentIntent(getDefalutIntent(Notification.FLAG_AUTO_CANCEL))// .setNumber(number)//显示数量.setTicker("测试通知来啦")// 通知首次出现在通知栏,带上升动画效果的.setWhen(System.currentTimeMillis())// 通知产生的时间,会在通知信息里显示.setPriority(Notification.PRIORITY_DEFAULT)// 设置该通知优先级.setAutoCancel(true)// 设置这个标志当用户单击面板就可以让通知将自动取消.setOngoing(false)// ture,设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接).setDefaults(Notification.DEFAULT_VIBRATE)// 向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置,使用defaults属性,可以组合:// Notification.DEFAULT_ALL Notification.DEFAULT_SOUND 添加声音 //// requires VIBRATE permission.setSmallIcon(R.drawable.ic_launcher);}public void shwoNotify(Object ob) {// 先设定RemoteViewsRemoteViews view_custom = new RemoteViews(context.getPackageName(),R.layout.view_custom);// 设置对应IMAGEVIEW的ID的资源图片view_custom.setImageViewResource(R.id.custom_icon, R.drawable.ico_qpp);// view_custom.setInt(R.id.custom_icon,"setBackgroundResource",R.drawable.icon);view_custom.setTextViewText(R.id.tv_custom_title, "QPP");view_custom.setTextViewText(R.id.tv_custom_content,"附近的网咖" + ob.toString());// view_custom.setTextViewText(R.id.tv_custom_time,// String.valueOf(System.currentTimeMillis()));// 设置显示// view_custom.setViewVisibility(R.id.tv_custom_time, View.VISIBLE);// view_custom.setLong(R.id.tv_custom_time,"setTime",// System.currentTimeMillis());//不知道为啥会报错,过会看看日志// 设置number// NumberFormat num = NumberFormat.getIntegerInstance();// view_custom.setTextViewText(R.id.tv_custom_num,// num.format(this.number));mBuilder = new Builder(context);mBuilder.setContent(view_custom).setContentIntent(getDefalutIntent(Notification.FLAG_AUTO_CANCEL)).setWhen(System.currentTimeMillis())// 通知产生的时间,会在通知信息里显示.setTicker("有新的消息 ").setPriority(Notification.PRIORITY_DEFAULT)// 设置该通知优先级.setAutoCancel(true).setOngoing(false)// 不是正在进行的 true为正在进行// 效果和.flag一样.setSmallIcon(R.drawable.ico_qpp);// 点击的意图ACTION是跳转到IntentIntent resultIntent = new Intent(context, MainActivity.class);resultIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);mBuilder.setContentIntent(pendingIntent);// mNotificationManager.notify(notifyId, mBuilder.build());Notification notify = mBuilder.build();notify.contentView = view_custom;// Notification notify = new Notification();// notify.icon = R.drawable.icon;// notify.contentView = view_custom;// notify.contentIntent =// getDefalutIntent(Notification.FLAG_AUTO_CANCEL);mNotificationManager.notify(notifyId, notify);}}


 初始化 BaseApplication 

import android.app.Application;public class BaseApplication extends Application{public static ClientSocket clientSocket;@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();
<span style="white-space:pre"></span>//初始化clientSocket = ClientSocket.reSocket(this);}}




  清单文件的配置  注册广播  打开网络权限


<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.umeng.message.example"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="8"        android:targetSdkVersion="22" />        <uses-permission android:name="android.permission.INTERNET" />    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:name="com.umeng.message.example.BaseApplication"        android:theme="@style/AppTheme" >        <activity            android:name="com.umeng.message.example.MainActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>                       <receiver             android:name="com.umeng.message.example.ClientReceiver"             >            <intent-filter android:priority="1000"                >                <action android:name="com.box"/>            </intent-filter>        </receiver>          </application></manifest>


 在app中使用调用   


 如果需要客户端登录后发送消息给服务端 服务端才开启对用户的推送 那么


BaseActivity

import android.app.Activity;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.content.Intent;import android.os.Bundle;public class BaseActivity extends Activity {/** Notification管理 */public NotificationManager mNotificationManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);initService();}/** * 初始化要用到的系统服务 */private void initService() {mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);}/**  * 清除当前创建的通知栏  */public void clearNotify(int notifyId){mNotificationManager.cancel(notifyId);//删除一个特定的通知ID对应的通知//mNotification.cancel(getResources().getString(R.string.app_name));}/** * 清除所有通知栏 * */public void clearAllNotify() {mNotificationManager.cancelAll();// 删除你发的所有通知}/** * @获取默认的pendingIntent,为了防止2.3及以下版本报错 * @flags属性:   * 在顶部常驻:Notification.FLAG_ONGOING_EVENT   * 点击去除: Notification.FLAG_AUTO_CANCEL  */public PendingIntent getDefalutIntent(int flags){PendingIntent pendingIntent= PendingIntent.getActivity(this, 1, new Intent(), flags);return pendingIntent;}}


MainActivity 

import java.net.InetSocketAddress;import java.net.Socket;import java.util.List;import java.util.Timer;import java.util.TimerTask;import android.app.AlarmManager;import android.app.Notification;import android.app.PendingIntent;import android.content.Intent;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.support.v4.app.NotificationCompat;import android.support.v4.app.NotificationCompat.Builder;import android.text.TextUtils;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.RemoteViews;import android.widget.TextView;import encryption.stringUtil.Util;import encryption.util.NumUtil;public class MainActivity extends BaseActivity {/** Notification构造器 */NotificationCompat.Builder mBuilder;/** Notification的ID */int notifyId = 100;String buffer = "";TextView txt1;Button send;EditText ed1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initNotify();txt1 = (TextView) findViewById(R.id.txt1);send = (Button) findViewById(R.id.send);ed1 = (EditText) findViewById(R.id.ed1);send.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {//if (clientWriteThread != null)//clientWriteThread.writeMessage("================");//else//System.err.println("null============ ");//发送消息到服务端BaseApplication.clientSocket.writeMessage("================");}});}<span style="white-space:pre"></span>//调用的方法public void ClientWriteMsg(Object ob){BaseApplication.clientSocket.writeMessage(ob);}}

 

 友情提示代码中的通知 请初始化再用。


 代码都在上面 就不发demo了   客户端是封装好了的,有断线重连的过程。



0 0
原创粉丝点击