Socket编程总结—Android手机服务器与多个Android手机客户端之间的通信(非阻塞)

根据前两周写的关于Socket编程的网络通信的代码,现在对有关知识和注意事项进行总结如下:

1.首先说下Android NIO中有关Socket编程的类

1)ServerSocketChannel类:服务器套接字通道相当于传统IO下的ServerSocket,通过ServerSocketChannel的socket()可以获得传统的ServerSocket,反过来使用ServerSocket的getChannel()可以获得ServerSocketChannel对象;实例化ServerSocketChannel可以直接通过ServerSocketChannel的静态方法open()就可以了。

2)SocketChannel类:套接字通道相当于传统IO下的Socket,通过SocketChannel的socket()可以获得传统的Socket,反过来使用Socket的getChannel()可以获得SocketChannel对象;

3)Selector选择器:在NIO中注册各种事件的方法主要使用Selector来实现的,我们可以使用Selector类的静态方法open()来实例化。

4)SelectionKey类:是个选择键,在NIO中选择器和选择键是很重要的,SelectionKey描述了NIO中比较重要的事件,如OP_ACCEPT、OP_READ、OP_WRITE。

2.然后说下非阻塞和阻塞模式的区别以及非阻塞模式的实现

1)非阻塞:所谓非阻塞就是说,服务器监听客户端连接的时候,如果没有客户连接,程序还接续执行,不会停在这里等待客户连接;或者客户连接上了,下一步就是等待客户发数据,如果不发,程序不会停留在这里,而是继续执行。反过来停留在这里,不继续执行就是阻塞。

2)非阻塞模式的实现:对于客户端来说,得到SocketChannel对象后,通过调用方法configureBlocking(false)来设置这个Socket为非阻塞状态。然后在配合Selector和SelectionKey的使用来与服务器进行交互。代码如下:

SocketChannel socket = new SocketChannel(ip,port);

socket.configureBlocking(false);
   mSelector = Selector.open();
   socket.register(mSelector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);

while (true) {

mSelector.select(0);
          Set<SelectionKey> readKeys = mSelector.selectedKeys();
          Iterator<SelectionKey> iterator = readKeys.iterator();
          while (iterator.hasNext()) {
              SelectionKey key = (SelectionKey) iterator.next();
              iterator.remove();
              if (key.isReadable()) {.....
              } else if (key.isWritable()) {.....
              }

}

}

3. 消息处理机制—Message Handler Looper

Message消息 Handler处理发送和接收消息 Looper管理消息,就是一个手柄

在什么情况下使用消息呢?比如一个子线程,在执行过程中要更改主线程UI的一个控件值,这个时候就需要发送一个消息给主线程,而使用消息处理机制也可以不干扰主线程执行其他操作,在主线程中只要Handler感应到有信息过来它会自己接收,然后处理。代码如下:

在主线程:声明一个Handler

Handler mHandler = new Handler() {

@Override
   public void handleMessage(Message msg) {
    super.handleMessage(msg);
         }
  };

在子线程:

public void sendMessage(String message, int what) {
     Message msg = mHandler.obtainMessage(what, 1, 1, message);
     mHandler.sendMessage(msg);
 }

注意子线程中的Handler必须是主线程声明的Handler,这样子线程发送的消息才能被主线程Handler认识接收。

4.遇到的问题

1)线程问题:Socket编程中,实现服务器与多个客户端的通信要尽量用多线程机制来实现,当服务器监听到一个客户端的连接就开辟一个线程专门负责与客户端的通信,如果客户端因为某个原因断开与服务器的连接就要及时关闭线程;当然如果是服务器断开了,那么就要关闭所有与客户通信的线程。Android开发中,要注意一点,比较耗时的操作最好开辟一个线程单独执行,不然主线程因为执行这个耗时的操作而耽误执行其他操作,这样导致程序效率很差。

2)网络问题:Android开发中,往往遇到服务器与客户端正在通信时候突然网络断了,这个时候就要关闭socket,但是在关闭socket的时候,双方要知道网络断了才能关闭,如果是人为关闭socket,另一方肯定能检测到,但是是网络突然断开,就不能检测到了,解决这样的方法就是,双方连接上后,每隔一段时间发一个保护数据包,这个数据包双方只管发送,接收不进行处理,如果在一段时间内,一方既没有发送正常的数据包也没有发送保护数据包,那就关闭socket,这样就解决了网络断开的问题导致一方没有及时关闭socket的问题。

3)socket关闭问题:在进行socket编程中,遇到异常或者其他需要断开连接的情况时,socket要及时关闭,而在关闭socket之前,要保证线程关闭;举个列子说下,客户端人为断开与服务器的连接,此时服务器就会检测到与这个客户的通道已经关闭而出现异常,此时服务器就要关闭线程和socket。

还有一个特别重要的问题,在Android开发中,如果服务器与客户端通信的时候,如果没有定义一个协议,只是简单的发送一个字符串,那么如果某一方发送一个空值,这个时候另一方就会默认的认为你没有发送数据。解决这个问题的办法就是,要么定义一个规范的协议发送数据,也就是每发送一个数据都有一个头,要么定义一个专门的数据包(如byte类型的 1 )代表一个空值。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

获取手机IP地址

第一种:
 public int getIpAddress() {
  WifiManager wifiManager = (WifiManager) this.context
    .getSystemService(Context.WIFI_SERVICE);
  // 判断wifi是否开启
  if (!wifiManager.isWifiEnabled()) {
   wifiManager.setWifiEnabled(true);
  }
  WifiInfo wifiInfo = wifiManager.getConnectionInfo();
  int ipAddress = wifiInfo.getIpAddress();
  return ipAddress;
 }
 private String intToIp(int i) {
  return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF)
    + "." + (i >> 24 & 0xFF);
 }

第二种

public String getInetIpAddress() {
  try {
   for (Enumeration<NetworkInterface> en = NetworkInterface
     .getNetworkInterfaces(); en.hasMoreElements();) {
    NetworkInterface intf = en.nextElement();
    for (Enumeration<InetAddress> ipAddr = intf.getInetAddresses(); ipAddr
      .hasMoreElements();) {
     InetAddress inetAddress = ipAddr.nextElement();
     return inetAddress.getHostAddress();
    }
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
  return null;
 }

http://www.cnblogs.com/crearo-ssy/archive/2012/08/16/2640612.html

时间: 2024-10-24 21:35:59

Socket编程总结—Android手机服务器与多个Android手机客户端之间的通信(非阻塞)的相关文章

iOS从零开始学习socket编程——高并发多线程服务器

在上一篇文章<iOS从零开始学习socket编程--HTTP1.0服务器端>中我们已经简单的接触了OC搭建的HTTP服务器. (地址http://blog.csdn.net/abc649395594/article/details/45131373) 出于用户体验和鲁棒性考虑,这里把这个HTTP服务器改进成多线程的. 首先,AnsycSocket这个类是基于OC的Runloop实现的,Runloop实现了方法的异步调用但并不支持多线程. 在这里首先简单区分一下多线程和方法异步调用的区别.他们都

socket编程:简单TCP服务器/客户端编程

其实对于socket:我们需要理解的是他提供了一种编程概念,利用socket就可以利用系统已经封装好的内部进行通信,我们只需要关注应用层方面的数据控制就OK了. 一. 套接字(socket) socket英文为插座的意思,也就是为用户提供了一个接入某个链路的接口.而在计算机网络中,一个IP地址标识唯一一台主机,而一个端口号标识着主机中唯一一个应用进程,因此"IP+端口号"就可以称之为socket. 两个主机的进程之间要通信,就可以各自建立一个socket,其实可以看做各自提供出来一个&

Socket编程实践(6) --TCPNotes服务器

僵尸进程过程 1)通过忽略SIGCHLD信号,避免僵尸进程 在server端代码中加入 signal(SIGCHLD, SIG_IGN); 2)通过wait/waitpid方法.解决僵尸进程 signal(SIGCHLD,onSignalCatch); void onSignalCatch(int signalNumber) { wait(NULL); } 3) 假设多个客户端同一时候关闭, 问题描写叙述如以下两幅图所看到的: watermark/2/text/aHR0cDovL2Jsb2cuY

Socket编程——怎么实现一个服务器多个客户端之间的连接

  1 package coreBookSocket; 2 3 import java.io.IOException; 4 import java.net.ServerSocket; 5 import java.net.Socket; 6 7 /* 8 * 这个方法的主要目地是为了用多线程的方法实现网络编程,让多个客户端可以同时连接到一个服务器 9 *1:准备工作和单个客户端编程类似,先建立服务器端的套接字,同时让客户端那边调用accept()方法来接受服务器端的信息 10 *2:这里面定一个w

socket编程:简单UDP服务器/客户端编程

对于之前的TCP协议而言,他是可靠的字节流传输,而在socket编程中,在不需要保证数据传输正确安全的情况下.或者由用户自己完成传输确认情况/服务端客户端自己实现数据传输.套接字编程也提供了UDP协议的方法. 基于UDP(不是面向连接)的socket编程,分为客户端和服务器端. 客户端的流程如下: (1)创建套接字(socket) (2)和服务器端进行通信(sendto) (3)关闭套接字 因为在socket编程中,UDP是针对数据报的数据传输,所以socket专门定义了UDP所使用的函数接口.

网络编程之Socket的TCP协议实现客户端与客户端之间的通信

我认为当你学完某个知识点后,最好是做一个实实在在的小案例.这样才能更好对知识的运用与掌握 如果你看了我前两篇关于socket通信原理的入门文章.我相信对于做出我这个小案列是完全没有问题的!! 既然是小案列.就难免会有很多不足,所以还请大家见谅.先说下用此案例实现的功能 利用Socke的TCP协议实现了 1:端与端之间的通信(客户端和客户端)包括发送文字,小文件,抖动效果 2:同步实现好友下线与上线的效果,即有其他客户端上线会通知其他已经在线的客户端 3:实现自定义通信协议 服务器窗体布局 布局很

Windows Socket 编程_ 简单的服务器/客户端程序

转载自:http://blog.csdn.net/neicole/article/details/7459021 一.程序运行效果图 二.程序源代码 三.程序设计相关基础知识 1.计算机网络    2.IP地址    3.协议    4.网络体系结构    5.TCP/IP体系结构与特点    6.客户机/服务器模式    7.TCP/IP特点    8.套接字的引入    9.面向 连接/无连接 的套接字的系统调用时序图/流程图 一.程序运行效果图 二.程序源代码 [cpp] view pla

Socket编程实践(9) --TCP服务器常见问题(4)

TCP/IP协议的11种状态 说明: 1.如下图(客户端与服务器都在本机:双方(server的子进程,与client)链接已经建立(ESTABLISHED),等待通信) 2.最先调用close的一端,后面会进入TIME_WAIT的状态(下图,server端首先关闭) 3.TIME_WAIT 时间是2MSL(报文的最长存活周期的2倍)     原因:(ACK y+1)如果发送失败可以重发. 服务器端处于closed状态,不等于客户端也处于closed状态.. 4.TCP/IP协议的第1种状态:图上

java服务器与linux c客户端之间udp通信

java服务器和 linux c客户端采用udp协议互相通信,最关键的点是数据结构的统一.比如说,在c中一个char型 是8bit,在java中,char 是16bit,所以c和java的char类型不能直接互相转换.在本例程中,c的char 类型和 java的byte类型,两个数据类型都是8bit,这样就保证了数据正确传输的基本条件之一. java服务器代码如下: import java.io.*; import java.lang.*; import java.net.*; public c