Android Socket编程android端服务器和客户端的实现

      其实和java实现的差不多,或本质是用java实现的,但由于android有自身的独特性,所以还是有一些要注意的点:


      我这个Demo是以服务器开启,然后客户端连上服务器后就可与服务器进行交互,客户端每向服务器发送一条信息,服务器就向客户端返回相应的信息,两端都在android端实现(网上有很多客户端用android实现的,没找到服务器也在android端实现的,另外网上的服务器基本都有开始没有关闭,我这里也添加了关闭,其中涉及多线程,希望能给大家一点启发,当然不足之处还望告知,我也是初学的学生),其中客户端基本借鉴《疯狂Android讲义》。

这个Demo的功能简单但扩展性很大,以这个为核心可以扩展出很多应用或功能(例如即时聊天,微型QQ等);


先上图:

服务器:



客户端:



服务器端代码(有注释不说了):

package com.example.multithreadserver;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;/** @Author mowen* @Time 2013/6/9*/public class MainActivity extends Activity {private static final int PORT = 9999; private List<Socket> mList = new ArrayList<Socket>();private volatile ServerSocket server=null;private ExecutorService mExecutorService = null; //线程池private String hostip;//本机IPprivate TextView mText1;private TextView mText2;private Button mBut1=null;   private Handler myHandler=null;private volatile boolean flag= true;//线程标志位@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);this.requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.main);hostip = getLocalIpAddress();  //获取本机IPmText1=(TextView) findViewById(R.id.textView1);mText1.setText(hostip);mText1.setEnabled(false);mText2=(TextView) findViewById(R.id.textView2);mBut1=(Button) findViewById(R.id.but1);mBut1.setOnClickListener(new Button1ClickListener());//取得非UI线程传来的msg,以改变界面myHandler =new Handler(){@SuppressLint("HandlerLeak")public void handleMessage(Message msg){if(msg.what==0x1234){mText2.append("\n" + msg.obj.toString());}    }};}//对button1的监听事件private final class Button1ClickListener implements View.OnClickListener{@Overridepublic void onClick(View v) {// TODO Auto-generated method stub//如果是“启动”,证明服务器是关闭状态,可以开启服务器if(mBut1.getText().toString().equals("启动")){System.out.println("flag:"+flag);ServerThread serverThread=new ServerThread();flag=true;serverThread.start();mBut1.setText("关闭");}else{try {flag=false;server.close();for(int p=0;p<mList.size();p++){Socket s=mList.get(p);s.close();}mExecutorService.shutdownNow();mBut1.setText("启动");System.out.println("服务器已关闭");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}//Server端的主线程class ServerThread extends Thread {public void stopServer(){try {              if(server!=null){                 server.close();System.out.println("close task successed");  }} catch (IOException e) {             System.out.println("close task failded");        }}public void run() {try {server = new ServerSocket(PORT);} catch (IOException e1) {// TODO Auto-generated catch blockSystem.out.println("S2: Error");e1.printStackTrace();}mExecutorService = Executors.newCachedThreadPool();  //创建一个线程池System.out.println("服务器已启动...");Socket client = null;while(flag) {try {System.out.println("S3: Error");client = server.accept(); System.out.println("S4: Error");//把客户端放入客户端集合中mList.add(client);mExecutorService.execute(new Service(client)); //启动一个新的线程来处理连接}catch ( IOException e) {System.out.println("S1: Error");e.printStackTrace();}}}}    //获取IPv6的IP地址/*public String getLocalIpAddress() {  try {  for (Enumeration<NetworkInterface> en = NetworkInterface  .getNetworkInterfaces(); en.hasMoreElements();) {  NetworkInterface intf = en.nextElement();  for (Enumeration<InetAddress> enumIpAddr = intf  .getInetAddresses(); enumIpAddr.hasMoreElements();) {  InetAddress inetAddress = enumIpAddr.nextElement();  if (!inetAddress.isLoopbackAddress()) {  return inetAddress.getHostAddress().toString();  }  }  }  } catch (SocketException ex) {  Log.e("WifiPreference IpAddress", ex.toString());  }  return null;  }  *///获取本地IPpublic static String getLocalIpAddress() {  try {  for (Enumeration<NetworkInterface> en = NetworkInterface  .getNetworkInterfaces(); en.hasMoreElements();) {  NetworkInterface intf = en.nextElement();  for (Enumeration<InetAddress> enumIpAddr = intf  .getInetAddresses(); enumIpAddr.hasMoreElements();) {  InetAddress inetAddress = enumIpAddr.nextElement();  if (!inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress()) {  return inetAddress.getHostAddress().toString();  }  }  }  } catch (SocketException ex) {  Log.e("WifiPreference IpAddress", ex.toString());  }  return null; }//处理与client对话的线程class Service implements Runnable {private volatile boolean kk=true;private Socket socket;private BufferedReader in = null;private String msg = "";public Service(Socket socket) {this.socket = socket;try {in = new BufferedReader(new InputStreamReader(socket.getInputStream()));msg="OK";this.sendmsg(msg);} catch (IOException e) {e.printStackTrace();}}public void run() {while(kk) {try {if((msg = in.readLine())!= null) {//当客户端发送的信息为:exit时,关闭连接if(msg.equals("exit")) {mList.remove(socket);//in.close();//socket.close();break;//接收客户端发过来的信息msg,然后发送给客户端。} else {Message msgLocal = new Message();msgLocal.what = 0x1234;msgLocal.obj =msg+" (客户端发送)" ;System.out.println(msgLocal.obj.toString());System.out.println(msg);myHandler.sendMessage(msgLocal);msg = socket.getInetAddress() + ":" + msg+"(服务器发送)";this.sendmsg(msg);}}} catch (IOException e) {System.out.println("close");kk=false;// TODO Auto-generated catch blocke.printStackTrace();}}}//向客户端发送信息public void sendmsg(String msg) {System.out.println(msg);PrintWriter pout = null;try {pout = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);pout.println(msg);}catch (IOException e) {e.printStackTrace();}}}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context=".MainActivity" ><Buttonandroid:id="@+id/but1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBottom="@+id/textView1"android:layout_alignParentRight="true"android:layout_marginRight="60dp"android:text="启动" /><TextViewandroid:id="@+id/textView2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@+id/textView1"android:layout_below="@+id/textView1"android:layout_marginTop="44dp"android:text="内容" /><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_alignParentTop="true"android:layout_marginLeft="15dp"android:layout_marginTop="48dp"android:text="IP" /></RelativeLayout>




客户端主要借鉴《疯狂Android讲义》:

UI端文件

package org.crazyit.net;import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;/***/
public class MultiThreadClient extends Activity
{// 定义界面上的两个文本框EditText input;TextView show;// 定义界面上的一个按钮Button send;Handler handler;// 定义与服务器通信的子线程ClientThread clientThread;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);input = (EditText) findViewById(R.id.input);send = (Button) findViewById(R.id.send);show = (TextView) findViewById(R.id.show);handler = new Handler() //①{@Overridepublic void handleMessage(Message msg){// 如果消息来自于子线程if (msg.what == 0x123){// 将读取的内容追加显示在文本框中show.append("\n" + msg.obj.toString());}}};clientThread = new ClientThread(handler);// 客户端启动ClientThread线程创建网络连接、读取来自服务器的数据new Thread(clientThread).start(); //①send.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v){try{// 当用户按下发送按钮后,将用户输入的数据封装成Message,// 然后发送给子线程的HandlerMessage msg = new Message();msg.what = 0x345;msg.obj = input.getText().toString();clientThread.revHandler.sendMessage(msg);// 清空input文本框input.setText("");}catch (Exception e){e.printStackTrace();}}});}
}

功能线程类:

/****/
package org.crazyit.net;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketTimeoutException;import android.os.Handler;
import android.os.Looper;
import android.os.Message;/***/
public class ClientThread implements Runnable
{private Socket s;// 定义向UI线程发送消息的Handler对象private Handler handler;// 定义接收UI线程的消息的Handler对象public Handler revHandler;// 该线程所处理的Socket所对应的输入流BufferedReader br = null;OutputStream os = null;public ClientThread(Handler handler){this.handler = handler;}public void run(){try{System.out.println("T1");s = new Socket("10.0.2.15", 9999);System.out.println("T2");br = new BufferedReader(new InputStreamReader(s.getInputStream()));os = s.getOutputStream();// 启动一条子线程来读取服务器响应的数据new Thread(){@Overridepublic void run(){String content = null;// 不断读取Socket输入流中的内容。try{while ((content = br.readLine()) != null){// 每当读到来自服务器的数据之后,发送消息通知程序界面显示该数据Message msg = new Message();msg.what = 0x123;msg.obj = content;handler.sendMessage(msg);System.out.println(msg.obj.toString());}}catch (IOException e){e.printStackTrace();}}}.start();// 为当前线程初始化LooperLooper.prepare();// 创建revHandler对象revHandler = new Handler(){@Overridepublic void handleMessage(Message msg){// 接收到UI线程中用户输入的数据if (msg.what == 0x345){// 将用户在文本框内输入的内容写入网络try{System.out.println("HHHHHHH"+msg.obj.toString());os.write((msg.obj.toString() + "\r\n").getBytes("utf-8"));}catch (Exception e){e.printStackTrace();}}}};// 启动LooperLooper.loop();}catch (SocketTimeoutException e1){System.out.println("网络连接超时!!");}catch (Exception e){e.printStackTrace();}}
}

布局文件很简单:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent">
<LinearLayout android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="wrap_content">
<!-- 定义一个文本框,它用于接受用户的输入 -->
<EditTextandroid:id="@+id/input"  android:layout_width="240dp" android:layout_height="wrap_content" />
<Buttonandroid:id="@+id/send"  android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingLeft="8px"android:text="@string/send"/>
</LinearLayout>
<TextViewandroid:id="@+id/show" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="top"android:background="#ffff"android:textSize="14dp"android:textColor="#f000"/>
</LinearLayout>

声明:真机上只需把客户端IP改成真机IP,即服务器上显示的IP即可通信

          虚拟机上同一个虚拟机可通信

          不同虚拟机由于Android虚拟机设计的原因,需要端口重定向等操作才能实现通信

附带两个工程的源码:http://download.csdn.net/detail/mowen1111/5553829

Android Socket编程android端服务器和客户端的实现相关推荐

  1. Android socket 编程 实现消息推送

    最近用socket写了一个消息推送的demo,在这里和大家分享一下. 主要实现了:一台手机向另外一台手机发送消息,这两台手机可以随时自由发送文本消息进行通信,类似我们常用的QQ. 效果图:    原理 ...

  2. Android Socket编程

    花了大概两天的时间,终于把Android的Socket编程给整明白了.抽空和大家分享一下:  Socket Programming on Android  Socket 编程基础知识:  主要分服务器 ...

  3. Android socket 编程 实现消息推送(一)

    最近用socket写了一个消息推送的demo,在这里和大家分享一下. 主要实现了:一台手机向另外一台手机发送消息,这两台手机可以随时自由发送文本消息进行通信,类似我们常用的QQ. 效果图        ...

  4. Android socket 编程 实现消息推送(二)

    上篇文章Android socket 编程 实现消息推送(一)讲到socket编程的消息推送原理,现在我们来看看基于Android客户机socket编程实现消息推送的过程. 根据消息推送的原理图,我们 ...

  5. 用JAVA SOCKET编程,读服务器几个字符,再写入本地显示

    Server: package cn.itcast.framework.socket;import java.io.BufferedReader; import java.io.IOException ...

  6. android开发重要控件,Android界面编程——Android基本控件

    Android界面编程 Android应用开发的一项重要内容就是界面开发.对于用户来说,不管APP包含的逻辑多么复杂,功能多么强大,如果没有提供友好的图形交互界面,将很难吸引最终用户. 作为一个程序员 ...

  7. Linux平台基于socket的文件传输服务器和客户端

    Linux平台基于socket的文件传输服务器和客户端 目录 前言 一.服务器程序结构 二.客户程序结构 三.代码 1.服务器主程序video_serv_fork.c 2.服务器子程序video_tr ...

  8. Socket编程(Android客户端+PC服务器端)

    一个多月没有写东西了,感觉像过了一个暑假...废话不多说了,今天来记录一下这两天学习Socket的内容.按照我研究思路来进行一步步的深入Socket. 一.什么是Socket 网络上的两个程序通过一个 ...

  9. Android Socket编程(多线程、双向通信)

    原帖地址:http://www.cnblogs.com/lknlfy/archive/2012/03/04/2379628.html 一.概述 关于Socket编程的基本方法在基础篇里已经讲过,今天把 ...

最新文章

  1. CIPAddressCtrl类的使用(IP地址与CString的互相转化)
  2. [Zhuan]Lua about
  3. 分区取模分库分表策略:多表事务分库内闭环解决方案
  4. java24小时运行一次_使用crontab每分钟执行一次脚本,每24小时执行一次脚本[关闭]...
  5. 14个新鲜的免费图标集
  6. 图书信息管理系统报告linux,C语言图书管理系统 带程序报告
  7. java 变量监听_java main函数里面的变量i怎么获取addActionListener监听里jtf_username.getText()的值?...
  8. 【Zabbix】Zabbix网络自动发现
  9. antdesign vue 表格,点击某行的事件写法
  10. RStudio的常用快捷键
  11. Sunday算法特征码搜索C++(支持通配符)
  12. ASC19 T4 CESM
  13. 当保险行业不再是压舱石,平安保险还保险吗?
  14. react 实战案例(webpack构建)
  15. 爱剪辑如何解决分段视频在串接处快两秒的问题
  16. phpstorm连接mysql
  17. 单元测试junit4
  18. java从小白到架构师学习路线
  19. 宏基服务器系统安装系统还原,宏碁win7系统重装教程
  20. 老毛桃制作linux u盘系统盘,使用U盘制作linux服务器启动盘,U盘制作普通系统盘的制作过程也是一样...

热门文章

  1. 探探左滑右滑简单实现
  2. 【SwiftUI模块】0004、SwiftUI-<探探App>喜欢手势卡片
  3. 新一代的数据库SQL审计服务 - SQL洞察
  4. linux usb hub 流程,Linux usb hub 处理
  5. 人工智能值得研究的领域有哪些?
  6. 同态加密:CKKS原理之旋转(Rotation)
  7. iOS应用调试检测以及反调试
  8. Unity 使用OpenXR和XR Interaction Toolkit 开发 HTCVive(Vive Cosmos)
  9. 现在或许是从事FPGA的最好时代!
  10. Javascript数据类型?(基本数据类型和引用数据类型)