Android客户端与PC服务端、android服务端通过WiFi通信

前期准备:我的是Linux Mint操作系统(总之折腾的过程中怀疑过是不是系统的问题),首先是要创建wifi热点给android手机使用,这个时候笔记本作为通信的服务器端,android手机作为客户端,通过socket进行通信。

1.在eclipse下写好服务器端的代码,包括监听的端口好,客户端的IP地址获取,发送的数据处理等,这里涉及到J2EE的环境配置,有时间我在写下,这个代码是直接百度到的,能用:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class Test {
    private ServerSocket server;
    private Socket client;
    private BufferedReader in;
    private PrintWriter out;

    public Test() {
        try {
            server = new ServerSocket(9400);
            while (true) {
                System.out.println("start!");
                // 获得客户端连接
                client = server.accept();
                // 获得客户端的IP和端口
                String remoteIP = client.getInetAddress().getHostAddress();
                int remotePort = client.getLocalPort();

                System.out.println("A client connected. IP:" + remoteIP
                        + ", Port: " + remotePort);
                System.out.println();

                // 获得 client 端的输入输出流,为进行交互做准备
                in = new BufferedReader(new InputStreamReader(
                        client.getInputStream()));
                out = new PrintWriter(client.getOutputStream(), false);

                // 获得 client 端发送的数据
                String tmp = in.readLine();
                // String content = new String(tmp.getBytes("utf-8"));
                System.out.println("Client message is: " + tmp);

                // 向 client 端发送响应数据
                out.println("Your message has been received successfully!.");

                // 关闭各个流
                out.close();
                in.close();
                // server.close();
            }
        } catch (Exception e) {
            // 发送响应,接收失败
            System.out.println(e.toString());
            out.println("Receive Error!");
        }
    }

    public static void main(String[] args) {
        new Test();
    }

}

代码看起来也不是太难,关键是Java EE的使用,尤其是服务器的配置,(配置教程涉及到tomcat的配置,以及服务器的建立),

Project name随便写好了,然后next---->next,需要把Generate web.xml deployment descriptor勾选上。注意:

Java Resources 下的src文件夹下里面放的是相关的类,这个类写完之后还在Webcontent文件夹--->WEB-INF文件夹下的web.xml里面配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>TomcatTest</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
    <servlet>
        <servlet-name>Test</servlet-name>
        <servlet-class>Test</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Test</servlet-name>
        <url-pattern></url-pattern>
    </servlet-mapping>
</web-app>
View Code

到这里你可以运行你的服务端,选中项目,右击选中Run as--->Run on server,到此你的网站基本上就发布成功了,在你的手机的浏览器中输入你PC端的IP地址,注意端口号是9400,比如我之前测试的用是的10.3.19.26:9400,就可以看到服务端返回的信息。

2.android端的程序比较简单,但是一开始的时候怎么都不能成功运行,最后发现的两个问题a.权限没有加,b.自从android3.0以后,android的运行机制不容许在主线程中使用网络的相关操作

我的值加了这几个权限,貌似也能够运行起来,呵呵:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

第二个问题,网上的一些代码太坑了,明明都是有问题,也不知道修改,下面写的很简单,没有图形界面,

package com.example.client;

import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {
    private Button btnConnect, btnSend;
    private Socket socket;
    private PrintStream output;
    private EditText editSend;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnConnect = (Button) findViewById(R.id.button1);
        btnSend = (Button) findViewById(R.id.button2);
        editSend = (EditText) findViewById(R.id.editText1);
        btnConnect.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                new Thread(runnable).start();//开启线程
            }
        });
        btnSend.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                sendMessage(editSend.getText().toString());

            }
        });

    }
    Runnable runnable = new Runnable() {
        
        @Override
        public void run() {
            // TODO Auto-generated method stub
            initClientSocket();
        }
    };

    public void initClientSocket() {
        try {
            EditText edit_ip = (EditText) MainActivity.this.findViewById(R.id.editText2);
            String ip = edit_ip.getText().toString().trim();
            socket = new Socket("10.3.19.26", 9400);
            output = new PrintStream(socket.getOutputStream(), true, "gbk");

        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            Toast.makeText(MainActivity.this, "请检查端口号是否为服务器IP",
                    Toast.LENGTH_LONG).show();
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            Toast.makeText(MainActivity.this, "服务器未开启", Toast.LENGTH_LONG)
                    .show();
            e.printStackTrace();
        }
        output.println("this is the message from client");
    }

    private void sendMessage(String str) {
        output.println(str);
    }

    public void closeSocket() {
        try {
            output.close();
            socket.close();
        } catch (IOException e) {
            System.out.println("error"+e);
        }
    }

}

基本上控件只有一个按钮,其他的都是没有用的,在按钮的监听器里面写的方法,就是使用Runable开启一个线程,在runable的方法中调用initClientSocket()方法,你会发现,里连接的代码很简单,我连接成功后就使用

output.println("this is the message from client");

这个就是返回给服务器的信息,一开始放在另一个按钮中的,但是考虑到上述的问题,还是直接在线程中发送(我测试过,在UI线程中不能使用这个方法,发送完了也没有反应)最终的服务器端接受的数据情况如下:

从下午到晚上总算弄完了2015-05-18 22:11:21,有时间把相关的配置弄下。

2015年5月19日星期二 21:53在github上看到一个程序,用的是内部异步任务方法处理的,放在这里参考下,很简单就是一个MainActivity.java:

  1     package com.example.androidclient;
  2 
  3     import java.io.ByteArrayOutputStream;
  4     import java.io.IOException;
  5     import java.io.InputStream;
  6     import java.net.Socket;
  7     import java.net.UnknownHostException;
  8 
  9     import android.os.AsyncTask;
 10     import android.os.Bundle;
 11     import android.app.Activity;
 12     import android.view.View;
 13     import android.view.View.OnClickListener;
 14     import android.widget.Button;
 15     import android.widget.EditText;
 16     import android.widget.TextView;
 17 
 18     public class MainActivity extends Activity {
 19         
 20         TextView textResponse;
 21         EditText editTextAddress, editTextPort;//用户自己输入的服务器端的地址和端口号 
 22         Button buttonConnect, buttonClear;
 23 
 24         @Override
 25         protected void onCreate(Bundle savedInstanceState) {
 26             super.onCreate(savedInstanceState);
 27             setContentView(R.layout.activity_main);
 28             
 29             editTextAddress = (EditText)findViewById(R.id.address);
 30             editTextPort = (EditText)findViewById(R.id.port);
 31             buttonConnect = (Button)findViewById(R.id.connect);
 32             buttonClear = (Button)findViewById(R.id.clear);
 33             textResponse = (TextView)findViewById(R.id.response);
 34             
 35             buttonConnect.setOnClickListener(buttonConnectOnClickListener);
 36             
 37             buttonClear.setOnClickListener(new OnClickListener(){
 38 
 39                 @Override
 40                 public void onClick(View v) {
 41                     textResponse.setText("");
 42                 }});
 43         }
 44         
 45         OnClickListener buttonConnectOnClickListener = 
 46                 new OnClickListener(){//连接的监听器
 47 
 48                     @Override
 49                     public void onClick(View arg0) {
 50                         MyClientTask myClientTask = new MyClientTask(
 51                                 editTextAddress.getText().toString(),
 52                                 Integer.parseInt(editTextPort.getText().toString()));//构造异步任务内部类
 53                         myClientTask.execute();
 54                     }};
 55 
 56         public class MyClientTask extends AsyncTask<Void, Void, Void> {//异步任务
 57             
 58             String dstAddress;
 59             int dstPort;
 60             String response = "";
 61             
 62             MyClientTask(String addr, int port){//构造方法,传进IP地址和对应的端口号
 63                 dstAddress = addr;
 64                 dstPort = port;
 65             }
 66 
 67             @Override
 68             protected Void doInBackground(Void... arg0) {
 69                 
 70                 Socket socket = null;//
 71                 
 72                 try {
 73                     socket = new Socket(dstAddress, dstPort);//建立连接,需要try-catch
 74                     
 75                     ByteArrayOutputStream byteArrayOutputStream = 
 76                             new ByteArrayOutputStream(1024);
 77                     byte[] buffer = new byte[1024];
 78                     
 79                     int bytesRead;
 80                     InputStream inputStream = socket.getInputStream();
 81                     
 82                     /*
 83                      * notice:
 84                      * inputStream.read() will block if no data return
 85                      */
 86                     while ((bytesRead = inputStream.read(buffer)) != -1){
 87                         byteArrayOutputStream.write(buffer, 0, bytesRead);
 88                         response += byteArrayOutputStream.toString("UTF-8");
 89                     }
 90 
 91                 } catch (UnknownHostException e) {
 92                     // TODO Auto-generated catch block
 93                     e.printStackTrace();
 94                     response = "UnknownHostException: " + e.toString();
 95                 } catch (IOException e) {
 96                     // TODO Auto-generated catch block
 97                     e.printStackTrace();
 98                     response = "IOException: " + e.toString();
 99                 }finally{
100                     if(socket != null){
101                         try {
102                             socket.close();
103                         } catch (IOException e) {
104                             // TODO Auto-generated catch block
105                             e.printStackTrace();
106                         }
107                     }
108                 }
109                 return null;
110             }
111 
112             @Override
113             protected void onPostExecute(Void result) {//更新UI线程
114                 textResponse.setText(response);
115                 super.onPostExecute(result);
116             }
117             
118         }
119 
120     }
View Code

那么对应的服务器android端的代码如下,写的也很简单浅显易懂:MainActivity.java

package com.example.androidserversocket;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;

import android.os.Bundle;
import android.app.Activity;
import android.widget.TextView;

public class MainActivity extends Activity {

    TextView info, infoip, msg;
    String message = "";
    ServerSocket serverSocket;//ServerSocket实例

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        info = (TextView) findViewById(R.id.info);
        infoip = (TextView) findViewById(R.id.infoip);
        msg = (TextView) findViewById(R.id.msg);
        
        infoip.setText(getIpAddress());//

        Thread socketServerThread = new Thread(new SocketServerThread());
        socketServerThread.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (serverSocket != null) {
            try {
                serverSocket.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    private class SocketServerThread extends Thread {

        static final int SocketServerPORT = 8080;
        int count = 0;

        @Override
        public void run() {
            try {
                serverSocket = new ServerSocket(SocketServerPORT);//监听端口
                MainActivity.this.runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        info.setText("I'm waiting here: "
                                + serverSocket.getLocalPort());
                    }
                });

                while (true) {//接受客户端的信息
                    Socket socket = serverSocket.accept();
                    count++;
                    message += "#" + count + " from " + socket.getInetAddress()
                            + ":" + socket.getPort() + "\n";

                    MainActivity.this.runOnUiThread(new Runnable() {

                        @Override
                        public void run() {
                            msg.setText(message);
                        }
                    });

                    SocketServerReplyThread socketServerReplyThread = new SocketServerReplyThread(
                            socket, count);
                    socketServerReplyThread.run();

                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

    private class SocketServerReplyThread extends Thread {

        private Socket hostThreadSocket;
        int cnt;

        SocketServerReplyThread(Socket socket, int c) {
            hostThreadSocket = socket;
            cnt = c;
        }

        @Override
        public void run() {
            OutputStream outputStream;
            String msgReply = "Hello from Android, you are #" + cnt;

            try {
                outputStream = hostThreadSocket.getOutputStream();
                PrintStream printStream = new PrintStream(outputStream);
                printStream.print(msgReply);
                printStream.close();

                message += "replayed: " + msgReply + "\n";

                MainActivity.this.runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        msg.setText(message);
                    }
                });

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                message += "Something wrong! " + e.toString() + "\n";
            }

            MainActivity.this.runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    msg.setText(message);
                }
            });
        }

    }

    private String getIpAddress() {
        String ip = "";
        try {
            Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
                    .getNetworkInterfaces();
            while (enumNetworkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = enumNetworkInterfaces
                        .nextElement();
                Enumeration<InetAddress> enumInetAddress = networkInterface
                        .getInetAddresses();
                while (enumInetAddress.hasMoreElements()) {
                    InetAddress inetAddress = enumInetAddress.nextElement();

                    if (inetAddress.isSiteLocalAddress()) {
                        ip += "SiteLocalAddress: " 
                                + inetAddress.getHostAddress() + "\n";
                    }
                    
                }

            }

        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            ip += "Something Wrong! " + e.toString() + "\n";
        }

        return ip;
    }
}
View Code

 

posted @ 2015-05-18 22:12  tomi_mint  阅读(1382)  评论(0编辑  收藏  举报