Android学习笔记四:socket通信

来源:互联网 发布:win10修改电脑mac地址 编辑:程序博客网 时间:2024/05/19 08:43

一、Android 开发之Socket编程 UDP和TCP通信实现

出处:http://www.linuxidc.com/Linux/2011-08/40053.htm

1、 Socket通信模型如下:


应用程序通过套接字可以进行通信,可以使用udp协议或者使用tcp协议

当客户端和服务器端的协议时相对应的,客户端使用tcp,那么服务器端使用tcp

 

2、 UDP协议:把数据打包成数据包,然后直接发送对应的ip地址,速度快,但是不保证

成功率,并且数据大小有限

TCP协议:首先连接接收方,然后发送数据,保证成功率, 速度慢

 

3、 TCP通信方式如下:

    

 

 

UDP通信不使用InputStreamOutputStream 

4、 UDP通信实现:

UDP使用DatagramSocket对象来实现 

UDP的客户端代码实现如下:

       public static void main(String[] args) {

       try {

           //首先创建一个DatagramSocket对象

           DatagramSocket socket = new DatagramSocket(4567);

           //创建一个InetAddree

InetAddress serverAddress = InetAddress.getByName("192.168.1.104");

           String str = "hello";  //这是要传输的数据

           byte data [] = str.getBytes();  //把传输内容分解成字节

           //创建一个DatagramPacket对象,并指定要讲这个数据包发送到网络当中的哪个、

地址,以及端口号

           DatagramPacket packet = new

 DatagramPacket(data,data.length,serverAddress,4567);

           //调用socket对象的send方法,发送数据

           socket.send(packet);

       } catch (Exception e) {

           // TODO Auto-generated catch block

           e.printStackTrace();

       }

}

 

 UDP的服务端代码实现如下:

//创建一个DatagramSocket对象,并指定监听的端口号

              DatagramSocket socket = new DatagramSocket(4567);

              byte data [] = new byte[1024];

              //创建一个空的DatagramPacket对象

               DatagramPacket packet = 

new DatagramPacket(data,data.length);

              //使用receive方法接收客户端所发送的数据,

              //如果客户端没有发送数据,该进程就停滞在这里

              socket.receive(packet);

              String result = new 

String(packet.getData(),packet.getOffset(),

packet.getLength());

        System.out.println("result--->" + result);

 

5、  TCP通信的实现:

TCP使用Socket对象

 

TCP协议客户端实现:

//创建一个Socket对象,指定服务器端的IP地址和端口号

           Socket socket = new Socket("192.168.1.104",4567);

           //使用InputStream读取硬盘上的文件

           InputStream inputStream = new

 FileInputStream("f://file/words.txt");

           //Socket当中得到OutputStream

           OutputStream outputStream = socket.getOutputStream();

           byte buffer [] = new byte[4*1024];

           int temp = 0 ;

           //InputStream当中的数据取出,并写入到OutputStream当中

           while((temp = inputStream.read(buffer)) != -1){

              outputStream.write(buffer, 0, temp);

           }

           outputStream.flush();

       } 

   TCP协议服务器端现实:

       //声明一个ServerSocket对象

        ServerSocket serverSocket = null;

        try {

                //创建一个ServerSocket对象,并让这个Socket4567端口监听

              serverSocket = new ServerSocket(4567);

        //调用ServerSocketaccept()方法,接受客户端所发送的请求,

//如果客户端没有发送数据,那么该线程就停滞不继续

              Socket socket = serverSocket.accept();

              //Socket当中得到InputStream对象

              InputStream inputStream = socket.getInputStream();

              byte buffer [] = new byte[1024*4];

              int temp = 0;

              //InputStream当中读取客户端所发送的数据

              while((temp = inputStream.read(buffer)) != -1){

                  System.out.println(new String(buffer,0,temp));

              }

           } catch (IOException e) {

              // TODO Auto-generated catch block

              e.printStackTrace();

           }

            serverSocket.close();

           } 

二、android之socket编程实例

出处:http://blog.csdn.net/x605940745/article/details/17001641

注意点:注册访问的网络权限;Android中UI线程不能有访问网络的操作,否则会报android.os.NetworkOnMainThreadException的异常

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <uses-permission   
  2.     android:name="android.permission.INTERNET"/>  

      Android开发联盟③ 433233634

实例一

客户端


[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.android.xiong.simplesocket;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6. import java.io.OutputStream;  
  7. import java.net.InetSocketAddress;  
  8. import java.net.Socket;  
  9. import java.net.SocketTimeoutException;  
  10.   
  11. import android.app.Activity;  
  12. import android.os.Bundle;  
  13. import android.os.Handler;  
  14. import android.os.Message;  
  15. import android.view.Menu;  
  16. import android.view.View;  
  17. import android.view.View.OnClickListener;  
  18. import android.widget.Button;  
  19. import android.widget.EditText;  
  20. import android.widget.TextView;  
  21.   
  22. public class MainActivity extends Activity {  
  23.     Socket socket = null;  
  24.     String buffer = "";  
  25.     TextView txt1;  
  26.     Button send;  
  27.     EditText ed1;  
  28.     String geted1;  
  29.     public Handler myHandler = new Handler() {  
  30.         @Override  
  31.         public void handleMessage(Message msg) {  
  32.             if (msg.what == 0x11) {  
  33.                 Bundle bundle = msg.getData();  
  34.                 txt1.append("server:"+bundle.getString("msg")+"\n");  
  35.             }  
  36.         }  
  37.   
  38.     };  
  39.   
  40.     @Override  
  41.     protected void onCreate(Bundle savedInstanceState) {  
  42.         super.onCreate(savedInstanceState);  
  43.         setContentView(R.layout.activity_main);  
  44.         txt1 = (TextView) findViewById(R.id.txt1);  
  45.         send = (Button) findViewById(R.id.send);  
  46.         ed1 = (EditText) findViewById(R.id.ed1);  
  47.         send.setOnClickListener(new OnClickListener() {  
  48.   
  49.             @Override  
  50.             public void onClick(View v) {  
  51.                 geted1 = ed1.getText().toString();  
  52.                 txt1.append("client:"+geted1+"\n");  
  53.                 //启动线程 向服务器发送和接收信息  
  54.                 new MyThread(geted1).start();  
  55.             }  
  56.         });  
  57.   
  58.     }  
  59.   
  60.     class MyThread extends Thread {  
  61.   
  62.         public String txt1;  
  63.   
  64.         public MyThread(String str) {  
  65.             txt1 = str;  
  66.         }  
  67.   
  68.         @Override  
  69.         public void run() {  
  70.             //定义消息  
  71.             Message msg = new Message();  
  72.             msg.what = 0x11;  
  73.             Bundle bundle = new Bundle();  
  74.             bundle.clear();  
  75.             try {  
  76.                 //连接服务器 并设置连接超时为5秒  
  77.                 socket = new Socket();  
  78.                 socket.connect(new InetSocketAddress("1.1.9.30"30000), 5000);  
  79.                 //获取输入输出流  
  80.                 OutputStream ou = socket.getOutputStream();  
  81.                 BufferedReader bff = new BufferedReader(new InputStreamReader(  
  82.                         socket.getInputStream()));  
  83.                 //读取发来服务器信息  
  84.                 String line = null;  
  85.                 buffer="";  
  86.                 while ((line = bff.readLine()) != null) {  
  87.                     buffer = line + buffer;  
  88.                 }  
  89.                   
  90.                 //向服务器发送信息  
  91.                 ou.write("android 客户端".getBytes("gbk"));  
  92.                 ou.flush();  
  93.                 bundle.putString("msg", buffer.toString());  
  94.                 msg.setData(bundle);  
  95.                 //发送消息 修改UI线程中的组件  
  96.                 myHandler.sendMessage(msg);  
  97.                 //关闭各种输入输出流  
  98.                 bff.close();  
  99.                 ou.close();  
  100.                 socket.close();  
  101.             } catch (SocketTimeoutException aa) {  
  102.                 //连接超时 在UI界面显示消息  
  103.                 bundle.putString("msg""服务器连接失败!请检查网络是否打开");  
  104.                 msg.setData(bundle);  
  105.                 //发送消息 修改UI线程中的组件  
  106.                 myHandler.sendMessage(msg);  
  107.             } catch (IOException e) {  
  108.                 e.printStackTrace();  
  109.             }  
  110.         }  
  111.     }  
  112.   
  113.     @Override  
  114.     public boolean onCreateOptionsMenu(Menu menu) {  
  115.         // Inflate the menu; this adds items to the action bar if it is present.  
  116.         getMenuInflater().inflate(R.menu.main, menu);  
  117.         return true;  
  118.     }  
  119.   
  120. }  

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:paddingBottom="@dimen/activity_vertical_margin"  
  6.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  7.     android:paddingRight="@dimen/activity_horizontal_margin"  
  8.     android:paddingTop="@dimen/activity_vertical_margin"  
  9.     tools:context=".MainActivity" >  
  10.   
  11.     <EditText   
  12.         android:id="@+id/ed1"  
  13.         android:layout_width="match_parent"  
  14.         android:layout_height="wrap_content"  
  15.         android:hint="给服务器发送信息"/>  
  16.     <Button   
  17.         android:id="@+id/send"  
  18.         android:layout_width="match_parent"  
  19.         android:layout_height="wrap_content"  
  20.         android:layout_below="@id/ed1"  
  21.         android:text="发送"/>  
  22.     <TextView   
  23.         android:id="@+id/txt1"  
  24.         android:layout_width="match_parent"  
  25.         android:layout_height="wrap_content"  
  26.         android:layout_below="@id/send"/>  
  27.       
  28.       
  29.   
  30.   
  31. </RelativeLayout>  

服务端

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.android.net;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.ServerSocket;  
  5. import java.net.Socket;  
  6. import java.util.ArrayList;  
  7. import java.util.List;  
  8.   
  9. public class AndroidService {  
  10.   
  11.   
  12.     public static void main(String[] args) throws IOException {  
  13.         ServerSocket serivce = new ServerSocket(30000);  
  14.         while (true) {  
  15.             //等待客户端连接  
  16.             Socket socket = serivce.accept();  
  17.             new Thread(new AndroidRunable(socket)).start();  
  18.         }  
  19.     }  
  20.   
  21. }  

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.android.net;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.BufferedWriter;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7. import java.io.InputStreamReader;  
  8. import java.io.OutputStream;  
  9. import java.io.OutputStreamWriter;  
  10. import java.io.PrintWriter;  
  11. import java.net.Socket;  
  12.   
  13. public class AndroidRunable implements Runnable {  
  14.   
  15.     Socket socket = null;  
  16.   
  17.     public AndroidRunable(Socket socket) {  
  18.         this.socket = socket;  
  19.     }  
  20.   
  21.     @Override  
  22.     public void run() {  
  23.         // 向android客户端输出hello worild  
  24.         String line = null;  
  25.         InputStream input;  
  26.         OutputStream output;  
  27.         String str = "hello world!";  
  28.         try {  
  29.             //向客户端发送信息  
  30.             output = socket.getOutputStream();  
  31.             input = socket.getInputStream();  
  32.             BufferedReader bff = new BufferedReader(  
  33.                     new InputStreamReader(input));  
  34.             output.write(str.getBytes("gbk"));  
  35.             output.flush();  
  36.             //半关闭socket    
  37.             socket.shutdownOutput();  
  38.             //获取客户端的信息  
  39.             while ((line = bff.readLine()) != null) {  
  40.                 System.out.print(line);  
  41.             }  
  42.             //关闭输入输出流  
  43.             output.close();  
  44.             bff.close();  
  45.             input.close();  
  46.             socket.close();  
  47.   
  48.         } catch (IOException e) {  
  49.             e.printStackTrace();  
  50.         }  
  51.   
  52.     }  
  53. }  

实例二

客户端

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.android.xiong.sockettwotest;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.os.Handler;  
  6. import android.os.Message;  
  7. import android.view.Menu;  
  8. import android.view.View;  
  9. import android.view.View.OnClickListener;  
  10. import android.widget.Button;  
  11. import android.widget.EditText;  
  12. import android.widget.TextView;  
  13.   
  14. public class MainActivity extends Activity {  
  15.   
  16.     // 定义界面上的两个文本框  
  17.     EditText input;  
  18.     TextView show;  
  19.     // 定义界面上的一个按钮  
  20.     Button send;  
  21.     Handler handler;  
  22.     // 定义与服务器通信的子线程  
  23.     ClientThread clientThread;  
  24.   
  25.     @Override  
  26.     protected void onCreate(Bundle savedInstanceState) {  
  27.         super.onCreate(savedInstanceState);  
  28.         setContentView(R.layout.activity_main);  
  29.         input = (EditText) findViewById(R.id.input);  
  30.         show = (TextView) findViewById(R.id.show);  
  31.         send = (Button) findViewById(R.id.send);  
  32.         handler = new Handler() {  
  33.   
  34.             @Override  
  35.             public void handleMessage(Message msg) {  
  36.                 // 如果消息来自子线程  
  37.                 if (msg.what == 0x123) {  
  38.                     // 将读取的内容追加显示在文本框中  
  39.                     show.append("\n" + msg.obj.toString());  
  40.                 }  
  41.             }  
  42.         };  
  43.         clientThread = new ClientThread(handler);  
  44.         // 客户端启动ClientThread线程创建网络连接、读取来自服务器的数据  
  45.         new Thread(clientThread).start();  
  46.         send.setOnClickListener(new OnClickListener() {  
  47.   
  48.             @Override  
  49.             public void onClick(View v) {  
  50.                 try {  
  51.                     // 当用户按下按钮之后,将用户输入的数据封装成Message  
  52.                     // 然后发送给子线程Handler  
  53.                     Message msg = new Message();  
  54.                     msg.what = 0x345;  
  55.                     msg.obj = input.getText().toString();  
  56.                     clientThread.revHandler.sendMessage(msg);  
  57.                     input.setText("");  
  58.   
  59.                 } catch (Exception e) {  
  60.   
  61.                 }  
  62.             }  
  63.         });  
  64.     }  
  65.   
  66.     @Override  
  67.     public boolean onCreateOptionsMenu(Menu menu) {  
  68.         getMenuInflater().inflate(R.menu.main, menu);  
  69.         return true;  
  70.     }  
  71.   
  72. }  

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.android.xiong.sockettwotest;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6. import java.io.OutputStream;  
  7. import java.net.InetSocketAddress;  
  8. import java.net.Socket;  
  9. import java.net.SocketTimeoutException;  
  10.   
  11. import android.os.Handler;  
  12. import android.os.Looper;  
  13. import android.os.Message;  
  14.   
  15. public class ClientThread implements Runnable {  
  16.     private Socket s;  
  17.     // 定义向UI线程发送消息的Handler对象  
  18.     Handler handler;  
  19.     // 定义接收UI线程的Handler对象  
  20.     Handler revHandler;  
  21.     // 该线程处理Socket所对用的输入输出流  
  22.     BufferedReader br = null;  
  23.     OutputStream os = null;  
  24.   
  25.     public ClientThread(Handler handler) {  
  26.         this.handler = handler;  
  27.     }  
  28.   
  29.     @Override  
  30.     public void run() {  
  31.         s = new Socket();  
  32.         try {  
  33.             s.connect(new InetSocketAddress("1.1.9.30"3000), 5000);  
  34.             br = new BufferedReader(new InputStreamReader(s.getInputStream()));  
  35.             os = s.getOutputStream();  
  36.             // 启动一条子线程来读取服务器相应的数据  
  37.             new Thread() {  
  38.   
  39.                 @Override  
  40.                 public void run() {  
  41.                     String content = null;  
  42.                     // 不断的读取Socket输入流的内容  
  43.                     try {  
  44.                         while ((content = br.readLine()) != null) {  
  45.                             // 每当读取到来自服务器的数据之后,发送的消息通知程序  
  46.                             // 界面显示该数据  
  47.                             Message msg = new Message();  
  48.                             msg.what = 0x123;  
  49.                             msg.obj = content;  
  50.                             handler.sendMessage(msg);  
  51.                         }  
  52.                     } catch (IOException io) {  
  53.                         io.printStackTrace();  
  54.                     }  
  55.                 }  
  56.   
  57.             }.start();  
  58.             // 为当前线程初始化Looper  
  59.             Looper.prepare();  
  60.             // 创建revHandler对象  
  61.             revHandler = new Handler() {  
  62.   
  63.                 @Override  
  64.                 public void handleMessage(Message msg) {  
  65.                     // 接收到UI线程的中用户输入的数据  
  66.                     if (msg.what == 0x345) {  
  67.                         // 将用户在文本框输入的内容写入网络  
  68.                         try {  
  69.                             os.write((msg.obj.toString() + "\r\n")  
  70.                                     .getBytes("gbk"));  
  71.                         } catch (Exception e) {  
  72.                             e.printStackTrace();  
  73.                         }  
  74.                     }  
  75.                 }  
  76.   
  77.             };   
  78.             // 启动Looper  
  79.             Looper.loop();  
  80.   
  81.         } catch (SocketTimeoutException e) {  
  82.             Message msg = new Message();  
  83.             msg.what = 0x123;  
  84.             msg.obj = "网络连接超时!";  
  85.             handler.sendMessage(msg);  
  86.         } catch (IOException io) {  
  87.             io.printStackTrace();  
  88.         }  
  89.   
  90.     }  
  91. }  

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:paddingBottom="@dimen/activity_vertical_margin"  
  6.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  7.     android:paddingRight="@dimen/activity_horizontal_margin"  
  8.     android:paddingTop="@dimen/activity_vertical_margin"  
  9.     tools:context=".MainActivity" >  
  10.   
  11.     <EditText  
  12.         android:id="@+id/input"  
  13.         android:layout_width="match_parent"  
  14.         android:layout_height="wrap_content"  
  15.         android:hint="@string/input" />  
  16.     <Button   
  17.         android:id="@+id/send"  
  18.         android:layout_width="match_parent"  
  19.         android:layout_height="wrap_content"  
  20.         android:text="@string/send"  
  21.         android:layout_below="@id/input"/>  
  22.     <TextView   
  23.         android:id="@+id/show"  
  24.         android:layout_width="match_parent"  
  25.         android:layout_height="wrap_content"  
  26.         android:layout_below="@id/send"/>  
  27.   
  28. </RelativeLayout>  

服务端


[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.android.net;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.ServerSocket;  
  5. import java.net.Socket;  
  6. import java.util.ArrayList;  
  7. import java.util.List;  
  8.   
  9. public class MyService {  
  10.   
  11.     // 定义保存所有的Socket  
  12.     public static List<Socket> socketList = new ArrayList<Socket>();  
  13.   
  14.     public static void main(String[] args) throws IOException {  
  15.         ServerSocket server = new ServerSocket(3000);  
  16.         while(true){  
  17.             Socket s=server.accept();  
  18.             socketList.add(s);  
  19.             //每当客户端连接之后启动一条ServerThread线程为该客户端服务  
  20.             new Thread(new ServiceThreada(s)).start();  
  21.               
  22.         }  
  23.     }  
  24.   
  25. }  


[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. package com.android.net;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStreamReader;  
  6. import java.io.OutputStream;  
  7. import java.net.Socket;  
  8.   
  9. public class ServiceThreada implements Runnable {  
  10.   
  11.     // 定义当前线程处理的Socket  
  12.     Socket s = null;  
  13.     // 该线程所处理的Socket所对应的输入流  
  14.     BufferedReader br = null;  
  15.   
  16.     public ServiceThreada(Socket s) {  
  17.         this.s = s;  
  18.         try {  
  19.             br = new BufferedReader(new InputStreamReader(s.getInputStream()));  
  20.         } catch (IOException e) {  
  21.             e.printStackTrace();  
  22.         }  
  23.     }  
  24.   
  25.     @Override  
  26.     public void run() {  
  27.   
  28.         String content = null;  
  29.         //采用循环不断的从Socket中读取客户端发送过来的数据  
  30.         while((content=readFromClient())!=null){  
  31.             //遍历socketList中的每个Socket  
  32.             //将读取到的内容每个向Socket发送一次  
  33.             for(Socket s:MyService.socketList){  
  34.                 OutputStream os;  
  35.                 try {  
  36.                     os = s.getOutputStream();  
  37.                     os.write((content+"\n").getBytes("gbk"));  
  38.                 } catch (IOException e) {  
  39.                     // TODO Auto-generated catch block  
  40.                     e.printStackTrace();  
  41.                 }  
  42.                   
  43.             }  
  44.         }  
  45.   
  46.     }  
  47.   
  48.     // 定义读取客户端的信息  
  49.     public String readFromClient() {  
  50.         try {  
  51.             return br.readLine();  
  52.         } catch (Exception e) {  

  1.             e.printStackTrace();  

  1.         }  
  2.         return null;  
  3.     }  
  4.   
  5. }  


三、Android socket通信(上)

今天我们介绍android下的socket通信,并编写一个小程序:android作为客户端,通过socket发送数据到我们的pc机,pc机就是服务器。


分两个实验完成:我们先在模拟器上实现,然后在真实的手机上实现。



1.
设置环境,两个实验均在ubuntu11.04下完成:
第一个实验是android模拟器作为客户端,第二个实验是真实的android手机作为客户端,两个实验的服务器都是我们的pc机,并且服务器端用c++实现,客户端用java实现:
第一个实验的ip配置:
主机eth0:192.168.1.2
pc服务器端口:9400



第二个实验的ip配置:
主机lwan0:192.168.1.100
pc服务器端口:9500




注意,第一个实验是android模拟器作为客户端,因此要设置主机的eth0的ip地址,而第二个实验是真实的android手机作为客户端,它和pc机(服务器)在一个无线路由器局域网里,因此我们要设置主机的lwan的ip地址,不过由于主机和真实手机的ip都是路由器dhcp自动分配的,因此无需额外的配置命令,你可以改成你自己的ip地址。


第一个实验的配置命令很简单:
sudo ifconfig eth0 192.168.1.2




首先介绍第一个实验:

由于模拟器的特殊性,因此我们需要将模拟器的端口映射到主机的某个端口,这样才可以和模拟器相互通信。



1.
端口映射:
在android sdk的platform-tools下有一个adb可执行程序,我的路径是android-sdk-linux_x86/platform-tools/adb,运行如下命令进行端口映射:

cd android-sdk-linux_x86/platform-tools

./adb forward tcp:9400 tcp:9400



上面命令的意思是将模拟器的9400端口映射到主机的9400端口,这样模拟器向192.168.1.2:9400发送的数据就会被映射到主机的9400端口(主机的ip地址是192.168.1.2),而我们的主机只要监听本地的9400端口即可。这里我们使用tcp socket




2.
环境配置完毕并了解了基本原理后,直接上代码,下面是客户端的代码,用java实现:
src/BogoclientActivity.java
[java] view plain copy
  1. package bogo.client.com;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.PrintStream;  
  5. import java.net.Socket;  
  6. import java.net.UnknownHostException;  
  7.   
  8. import android.app.Activity;  
  9. import android.os.Bundle;  
  10. import android.view.View;  
  11. import android.widget.Button;  
  12. import android.widget.EditText;  
  13. import android.widget.Toast;  
  14.   
  15.   
  16. public class BogoclientActivity extends Activity  
  17. {  
  18.   /* 服务器地址 */  
  19.   private final String SERVER_HOST_IP = "192.168.1.2";  
  20.   
  21.   /* 服务器端口 */  
  22.   private final int SERVER_HOST_PORT = 9400;  
  23.     
  24.   private Button btnConnect;  
  25.   private Button btnSend;  
  26.   private EditText editSend;  
  27.   private Socket socket;  
  28.   private PrintStream output;  
  29.   
  30.   
  31.   public void toastText(String message)  
  32.   {  
  33.     Toast.makeText(this, message, Toast.LENGTH_LONG).show();  
  34.   }  
  35.   
  36.   public void handleException(Exception e, String prefix)  
  37.   {  
  38.     e.printStackTrace();  
  39.     toastText(prefix + e.toString());  
  40.   }  
  41.   
  42.   /** Called when the activity is first created. */  
  43.   @Override  
  44.   public void onCreate(Bundle savedInstanceState)  
  45.   {  
  46.     super.onCreate(savedInstanceState);  
  47.     setContentView(R.layout.main);  
  48.   
  49.     initView();  
  50.   
  51.     btnConnect.setOnClickListener(new Button.OnClickListener()  
  52.     {  
  53.       @Override  
  54.       public void onClick(View v)  
  55.       {  
  56.         initClientSocket();  
  57.       }  
  58.     });  
  59.       
  60.     btnSend.setOnClickListener(new Button.OnClickListener()  
  61.     {  
  62.       @Override  
  63.       public void onClick(View v)  
  64.       {  
  65.         sendMessage(editSend.getText().toString());  
  66.       }  
  67.     });  
  68.   }  
  69.     
  70.   public void initView()  
  71.   {  
  72.     btnConnect = (Button)findViewById(R.id.btnConnect);  
  73.     btnSend = (Button)findViewById(R.id.btnSend);  
  74.     editSend = (EditText)findViewById(R.id.sendMsg);  
  75.   
  76.     btnSend.setEnabled(false);  
  77.     editSend.setEnabled(false);  
  78.   }  
  79.   
  80.   public void closeSocket()  
  81.   {  
  82.     try  
  83.     {  
  84.       output.close();  
  85.       socket.close();  
  86.     }  
  87.     catch (IOException e)  
  88.     {  
  89.       handleException(e, "close exception: ");  
  90.     }  
  91.   }  
  92.     
  93.   private void initClientSocket()  
  94.   {  
  95.     try  
  96.     {  
  97.       /* 连接服务器 */  
  98.       socket = new Socket(SERVER_HOST_IP, SERVER_HOST_PORT);  
  99.   
  100.       /* 获取输出流 */  
  101.       output = new PrintStream(socket.getOutputStream(), true"utf-8");  
  102.         
  103.       btnConnect.setEnabled(false);  
  104.       editSend.setEnabled(true);  
  105.       btnSend.setEnabled(true);  
  106.     }  
  107.     catch (UnknownHostException e)  
  108.     {  
  109.       handleException(e, "unknown host exception: " + e.toString());  
  110.     }  
  111.     catch (IOException e)  
  112.     {  
  113.       handleException(e, "io exception: " + e.toString());  
  114.     }  
  115.   }  
  116.     
  117.   private void sendMessage(String msg)  
  118.   {  
  119.     output.print(msg);  
  120.   }  
  121. }  


layout/main.xml

[plain] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <TextView  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:text="@string/hello" />  
  11.   
  12.     <Button  
  13.         android:id="@+id/btnConnect"  
  14.         android:layout_width="fill_parent"  
  15.         android:layout_height="wrap_content"  
  16.         android:text="@string/connect" />  
  17.   
  18.     <EditText  
  19.         android:id="@+id/sendMsg"  
  20.         android:layout_width="match_parent"  
  21.         android:layout_height="wrap_content"  
  22.         android:inputType="text" />  
  23.   
  24.     <Button  
  25.         android:id="@+id/btnSend"  
  26.         android:layout_width="fill_parent"  
  27.         android:layout_height="wrap_content"  
  28.         android:text="@string/send" />  
  29.   
  30. </LinearLayout>  



不要忘了,在AndroidManifest.xml中添加访问网络权限:
<uses-permission android:name="android.permission.INTERNET" />



把上面的代码编译并下载到模拟器中


3.
服务器端的代码,用c++实现:
server.c

[cpp] view plain copy
  1. #include <sys/types.h>  
  2. #include <sys/socket.h>  
  3. #include <netinet/in.h>  
  4. #include <arpa/inet.h>  
  5. #include <unistd.h>  
  6. #include <stdlib.h>  
  7. #include <stdio.h>  
  8.   
  9. #define PORT 9400  
  10. #define MAX_BUFFER 1024  
  11.   
  12.   
  13. int main()  
  14. {  
  15.   /* create a socket */  
  16.   int server_sockfd = socket(AF_INET, SOCK_STREAM, 0);  
  17.     
  18.   struct sockaddr_in server_addr;  
  19.   server_addr.sin_family = AF_INET;  
  20.   server_addr.sin_addr.s_addr = inet_addr("192.168.1.2");  
  21.   server_addr.sin_port = htons(PORT);  
  22.     
  23.   /* bind with the local file */  
  24.   bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));  
  25.     
  26.   /* listen */  
  27.   listen(server_sockfd, 5);  
  28.     
  29.   int size;  
  30.   char buffer[MAX_BUFFER + 1];  
  31.   int client_sockfd;  
  32.   struct sockaddr_in client_addr;  
  33.   socklen_t len = sizeof(client_addr);  
  34.     
  35.   /* accept a connection */  
  36.   printf("waiting connection...\n");  
  37.   client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &len);  
  38.   printf("connection established!\n");  
  39.       
  40.   while(1)  
  41.   {  
  42.     printf("waiting message...\n");  
  43.       
  44.     /* exchange data */  
  45.     size = read(client_sockfd, buffer, MAX_BUFFER);  
  46.     buffer[size] = '\0';  
  47.     printf("Got %d bytes: %s\n", size, buffer);  
  48.   }  
  49.   
  50.   /* close the socket */  
  51.   close(client_sockfd);  
  52.         
  53.   return 0;  
  54. }  

Makefile:

[plain] view plain copy
  1. all: server.c  
  2.     gcc -g -Wall -o server server.c  
  3.   
  4. clean:  
  5.     rm -rf *.o server  



4.
运行结果:


首先运行服务器代码,然后运行模拟器的bogoclient程序,如下图,pc机正等待模拟器连接,并且未连接之前模拟器的文本对话框和send按钮都是不可用的:




点击connect按钮进行连接,连接成功后我们发现文本框和send按钮可用了,connect按钮不可用了,并且主机从等待连接状态变成了等待数据状态:





输入一些文本后按send按钮,pc机就会打印出模拟器发来的文本数据:



注意,如果模拟器连接时提示Connect refused,那么把模拟器的bogoclient和pc机上的server都结束掉,然后重新开始。



代码不过多解释了,注释挺详细的,有关pc机上的tcp通信,可以参考:

http://blog.csdn.net/htttw/article/details/7519964



最后,我把这个服务器和客户端两个程序都上传上来,供大家下载:

http://download.csdn.net/detail/htttw/4307606



在下一篇里,我们要把这个程序移植到真实的android手机上了:

http://blog.csdn.net/htttw/article/details/7574409


0 0
原创粉丝点击