Android Socket编程android端服务器和客户端的实现
来源:互联网 发布:网络传销一般崩盘时间 编辑:程序博客网 时间:2024/03/29 19:09
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;//本机IP private 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; } *///获取本地IP public 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" > <Button android: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="启动" /> <TextView android: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="内容" /> <TextView android: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端服务器和客户端的实现
- Android基于客户端和服务器的Socket编程例子之Socket基础通讯--socket相关知识
- Android基于客户端和服务器的Socket编程例子之Socket基础通讯--socket模型使用
- java网络编程----------Socket实现客户端和服务器的连接
- Socket实现Android客户端与服务器的通信
- 服务器和客户端的socket编程
- socket编程客户端和服务器
- 在Android上实现SSL握手,实现服务器和客户端之间Socket交互
- 在Android上实现SSL握手(客户端需要密钥和证书),实现服务器和客户端之间Socket交互
- 主题:在Android上实现SSL握手(客户端需要密钥和证书),实现服务器和客户端之间Socket交互
- 转载:在Android上实现SSL握手(客户端需要密钥和证书),实现服务器和客户端之间Socket交互
- 网络编程:使用Socket实现简单的服务器和客户端的通信
- Android的Socket编程实现
- android下socket编程问题:服务器关闭时,客户端发送请求的异常处理
- android下socket编程问题:服务器关闭时,客户端发送请求的异常处理
- 多线程Socket编程实现服务器与客户端的连接
- Android客户端与PC服务器实现Socket通信(wifi)
- Android客户端与PC服务器实现Socket通信(wifi)
- Django 加密模块的应用
- Eclipse 配置 启动优化 快捷键
- 老外对pro中Install阐述
- 《Unix编程艺术》chm 电子书下载
- Throwable.fillInStackTrace()的用法
- Android Socket编程android端服务器和客户端的实现
- Android反射机制实现与原理
- hadoop深入研究:(三)——hdfs数据流
- Xml 转 数组
- linux 服务器时间函数
- hibernate执行sql语句,转换为MAP
- Java Socket实战之六 使用NIO包实现Socket通信
- 开源框架MVVM Light Toolkit for wpf/silverlight系列
- 用VC编译ffmpeg(包括汇编优化) 的心得和体会