实际项目汇中的socket通讯

演示过程

首先开启服务器

打开一个SDK大于4.4的手机---B


打开一个SDK小于4.4的手机---A

相互发送一条消息,对方就可以收到,当然这些消息都是通过服务器【转发】过来的

MainActivity

/**

*  Activity启动以后就开启服务,服务开启后就通过ConnectorManager调用Connector中的connect方法对客户端进行认证

*  认证是通过三次握手完成的,服务器为所有认证的客户端新建一个线程,通过此线程和客户端通讯

*  当点击发送按钮后,通过ConnectorManager调用Connector中的方法把消息发送到一个阻塞队列中,最终发给服务器

*  服务器收到消息后将其【转发】给指定客户端的Connector的阻塞队列中,客户端又通过listener.pushData(text)转发消息

*  由于ConnectorManager注册了Connector的回调,ConnectorService又注册了ConnectorManager的回调

*  所以最终调用的是ConnectorService的回调方法pushData(data) ,而此方法又通过发送一条广播将消息转发出去

*  此广播会被PushReceiver接收到,因为其是在MainActivity注册的,所以最终MainActivity也收到了服务器转发过来的消息

*/

public class MainActivity extends Activity implements OnClickListener {

private EditText et;

private Button send;

private PushReceiver receiver = new PushReceiver();

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

et = (EditText) findViewById(R.id.et);

send = (Button) findViewById(R.id.send);

send.setOnClickListener(this);

//Activity启动以后就开启服务

startService(new Intent(this, ConnectorService.class));

//在代码中动态注册广播,这种类型的广播不是常驻型广播,也就是说广播跟随程序的生命周期

IntentFilter filter = new IntentFilter();

filter.addAction(PushReceiver.ACTION_TEXT);

registerReceiver(receiver, filter);

}

@Override

protected void onDestroy() {

super.onDestroy();

unregisterReceiver(receiver);

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.send:

sendMessage();

break;

default:

break;

}

}

public void sendMessage() {

final String content = et.getText().toString().trim();

if (TextUtils.isEmpty(content)) return;

String sender = null;

String token = null;

String receiver = null;

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {

sender = "B";

receiver = "A";

token = "B";

} else {

sender = "A";

token = "A";

receiver = "B";

}

Request request = new TextRequest(sender, token, receiver, content);

ConnectorManager.getInstance().putRequest(request);

}

}

PushReceiver

public class PushReceiver extends BroadcastReceiver {

/**发送文本信息的事件*/

public static final String ACTION_TEXT = "com.bqt.action.text";

public static final String DATA_KEY = "data";

@Override

public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

Log.d("activity", "receive");

if (PushReceiver.ACTION_TEXT.equals(action)) {

String text = intent.getStringExtra(PushReceiver.DATA_KEY);

Toast.makeText(context, text, Toast.LENGTH_SHORT).show();

}

}

}

Connector 

/**用一个类把与Socket相关的连接、发送消息、断开连接等方法抽离出来,并通过回调方式把结果返回*/

public class Connector {

public static final String DST_NAME = "192.168.31.165";

public static final int DST_PORT = 10002;

private Socket client;

//有界阻塞队列,当容量满时往BlockingQueue中添加数据时会阻塞,当容量为空时取元素操作会阻塞。

private ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(8);

private ConnectorListener listener;

/**连接*/

public void connect() {

try {

// 三次握手

if (client == null || client.isClosed()) client = new Socket(DST_NAME, DST_PORT);

new Thread(new Runnable() {

@Override

public void run() {

// 数据通讯

OutputStream os;

try {

os = client.getOutputStream();

// os.write(content.getBytes());

while (true) {

String content = queue.take();

os.write(content.getBytes());

}

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

try {

InputStream is = client.getInputStream();

byte[] buffer = new byte[1024];

int len = -1;

while ((len = is.read(buffer)) != -1) {

final String text = new String(buffer, 0, len);

System.out.println("服务器转发的消息 : " + text);

//获取服务器向客户端转发的消息

if (listener != null) listener.pushData(text);

}

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

} catch (Exception e) {

e.printStackTrace();

}

}

/**认证*/

public void auth(String auth) {

putRequest(auth);

}

/**发送消息*/

public void putRequest(String content) {

try {

queue.put(content);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

/**断开连接*/

public void disconnect() {

try {

if (client != null && !client.isClosed()) {

client.close();

client = null;

}

} catch (IOException e) {

e.printStackTrace();

}

}

public void setConnectorListener(ConnectorListener listener) {

this.listener = listener;

}

}

ConnectorListener

public interface ConnectorListener {

void pushData(String data);

}

ConnectorManager

/**管理Connector的方法,目的:隐藏实现细节,简化对外暴露的方法*/

public class ConnectorManager implements ConnectorListener {

private static ConnectorManager instance;

private Connector connector;

private ConnectorListener listener;

private ConnectorManager() {

}

public static ConnectorManager getInstance() {

if (instance == null) {

synchronized (ConnectorManager.class) {

if (instance == null) instance = new ConnectorManager();

}

}

return instance;

}

/**连接、注册监听、认证*/

public void connnect(AuthRequest auth) {

connector = new Connector();

connector.setConnectorListener(this);

connector.connect();

connector.auth(auth.getData());

}

/**发送消息*/

public void putRequest(Request request) {

connector.putRequest(request.getData());

}

@Override

public void pushData(String data) {

if (listener != null) listener.pushData(data);

}

public void setConnectorListener(ConnectorListener listener) {

this.listener = listener;

}

}

ConnectorService

/**

* 作用①:Activity启动以后就开启服务通过ConnectorManager调用Connector中的connect方法对客户端进行认证

* 作用②:客户端收到服务器转发过来的消息后通过ConnectorService的pushData通过发送一条广播将消息转发出去

* 注意:为简化代码,若客户端(手机)SDK版本小于4.4则定义为A手机,否则就定义为B手机,请演示时一定注意!

*/

public class ConnectorService extends Service implements ConnectorListener {

private ConnectorManager connectorManager;

@Override

public IBinder onBind(Intent intent) {

return null;

}

@Override

public void onCreate() {

super.onCreate();

connectorManager = ConnectorManager.getInstance();

new Thread(new Runnable() {

@Override

public void run() {

connectorManager.setConnectorListener(ConnectorService.this);

//认证

AuthRequest request = null;

//当前SDK版本大于4.4---暂时这么区分两部手机,实际肯定不是这么搞得

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) request = new AuthRequest("B", "B");

else request = new AuthRequest("A", "A");

connectorManager.connnect(request);

}

}).start();

}

@Override

public void pushData(String data) {

Log.d("coreService", "data : " + data);

Intent intent = new Intent();

intent.setAction(PushReceiver.ACTION_TEXT);

intent.putExtra(PushReceiver.DATA_KEY, data);

sendBroadcast(intent);

}

}

服务端代码

public class TCPServer {

private static final int port = 10002;

/**保存并标记所有建立连接的客户端*/

private static Map<String, Socket> clients = new LinkedHashMap<String, Socket>();

public static void main(String[] args) {

try {

ServerSocket server = new ServerSocket(port);

while (true) {

System.out.println("准备阻塞...");

// 获得客户端连接,阻塞式方法

final Socket client = server.accept();

System.out.println("阻塞完成...");

//每连接一个客户端就新建一个线程

new Thread(new Runnable() {

@Override

public void run() {

try {

// 获取客户端的输入流,也即客户端发送的数据。

//注意输入流和输出流相对于内存设备而言,将外设中的数据读取到内存中就是输入

InputStream is = client.getInputStream();

// 输出流,给客户端写数据

OutputStream os = client.getOutputStream();

byte[] buffer = new byte[1024];

int len = -1;

System.out.println("准备read...");

while ((len = is.read(buffer)) != -1) {

System.out.println("read完成...");

String text = new String(buffer, 0, len);

System.out.println(text);

//将客户端发送的json串转换为map

Map<String, String> map = new Gson().fromJson(text, new TypeToken<Map<String, String>>() {

}.getType());

String type = map.get("type");

if ("request".equals(type)) {

String action = map.get("action");

if ("auth".equals(action)) {

// 认证消息处理

String sender = map.get("sender");

System.out.println(sender + "认证");

// 放到容器当中

clients.put(sender, client);

} else if ("text".equals(action)) {

// 文本消息

String sender = map.get("sender");//客户端写死了

String receiver = map.get("receiver");

String content = map.get("content");

Socket s = clients.get(receiver);

if (s != null) {// 在线

OutputStream output = s.getOutputStream();

output.write(content.getBytes());

} else {    // 离线

}

}

} else System.out.println("格式错误");

}

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

来自为知笔记(Wiz)

附件列表

时间: 2024-10-19 10:56:18

实际项目汇中的socket通讯的相关文章

关于Socket通讯中的Close_wait状态

关于Socket通讯中的Close_wait状态 文/转 编辑 编者按:使用Socket通讯,有时我们查看端口状态的时候,经常会发现Socket处于close_wait状态,从而影响系统性能,此文或许会给你一些答案. 最近遇到的一个关于socket.close的问题,在某个应用服务器出现的状况(执行netstat -np | grep tcp): tcp        0      0 10.224.122.16:50158         10.224.112.58:8788        

项目笔记---C#异步Socket示例

概要 在C#领域或者说.net通信领域中有着众多的解决方案,WCF,HttpRequest,WebAPI,Remoting,socket等技术.这些技术都有着自己擅长的领域,或者被合并或者仍然应用于某些场合.本文主要介绍Socket通讯,因其有着跨平台.跨语言.高性能等优势,适合某些情况的应用以及性能优越的解决方案. 本文是基于一个小项目中的应用,使用了异步方式的Socket通讯,性能上达到多客户端多点通讯,大文件(M-G级别)的文件传输,异步长连接上的性能优势,但此项目也有些不足:未进行大量的

客户端技术的一点思考(数据存储用SQLite, XMPP通讯用Gloox, Web交互用LibCurl, 数据打包用Protocol Buffer, socket通讯用boost asio)

今天看到CSDN上这么一篇< 彻底放弃没落的MFC,对新人的忠告!>, 作为一个一直在Windows上搞客户端开发的C++程序员,几年前也有过类似的隐忧(参见 落伍的感觉), 现在却有一些不同的想法. 首先,个人职业发展是否成功, 技术只是其中一小块,尤其是在大公司, 更多的是依靠所谓的软实力.作为一个对技术有追求的工匠,我们下面重点说技术相关的. 现在回头看计算机行业的发展,我们看到不同的发展阶段: 1. PC时代,这个时代离我们并不遥远, 也有是2000年前后, 该时代最鲜明的特征是Win

python进阶---Python中的socket编程(一)

初识socket编程 一.前言 socket基于C\S架构(客户端\服务端)的编程模型,在Python中是以socket模块存在的. Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议. 所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规

iOS开发socket通讯

写写socket通讯那些事儿.     socket通讯公司用于给服务器发一些指令用于控制智能家居类的设备.socket无非就是发过来发过去,至于具体内容跟服务器协商就好.接下来先说说与socket通讯配合使用的socket Tool 的mac 工具.首先打开工具(工具连接以及socket用到的文件:SocketToolfor_mac_and_Third_for_xocde_socket.zip)选择Tcp Server 然后点击创建 端口号输入一个数字,60000 把. 注意可能完成之后这个数

试解析Tomcat运行原理(一)--- socket通讯

关于这篇文章也确实筹划了很久,今天决定开篇写第一篇,说起tomcat首先很容易联想到IIS,因为我最开始使用的就是.net技术,我第一次使用asp写学生成绩管理系统后,很茫然如何让别人都能看到或者说使用这个系统呢?由此认识了IIS,它是一个web容器,天生的多线程,及时响应用户提交的请求返回html页面,这就是我了解的最初的web容器的功能,由此我们来认识tomcat也并不困难,可以的话,在了解完tomcat后我们可以继续了解jboss.jetty等,好我们进入主题. 我们在平时开发的过程中是在

c# TCP Socket通讯基础

在做网络通讯方面的程序时,必不可少的是Socket通讯. 那么我们需要有一套既定的,简易的通讯流程. 如下: <pre name="code" class="csharp">public class PublicSocket { public const string DOWNLOAD_STATUS_WAIT = "1"; public const string DOWNLOAD_STATUS_PAUSE = "2"

Java中的Socket通信(一)Socket介绍

Socket又称"套接字",应用程序通常通过"套接字"向网络中发出请求或者应答网络请求. 在Java中,Socket和ServeSocket类库位于Java.net包中.SeverSocket用于服务器端,Socket是建立网络连接时使用的.在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话.对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同的级别.不管是Socket还是ServerSocket它

iOS项目开发中的知识点与问题收集整理

注:本文并非绝对原创 大部分内容摘自 http://blog.csdn.net/hengshujiyi/article/details/20943045 文中有些方法可能已过时并不适用于现在的开发环境. 1,Search Bar 怎样去掉背景的颜色(storyboard里只能设置background颜色,可是发现clear Color无法使用). 其实在代码里还是可以设置的,那就是删除背景view  [[self.searchBar.subviews objectAtIndex:0] remov