Android网络之简单服务器与客户端双向接收

来源:互联网 发布:韩顺平 php大牛班课程 编辑:程序博客网 时间:2024/05/21 08:03

这里我们通过Socket实现功能;

我们在PC机端用Java编写一个简单的服务器,向客户端发送数据同时接收客户端发送过来的数据并打印出来。同理,我们的Android APP作为客户端,同样向服务端发送数据,并且接收其发送来的数据,并通过TextView显示出来。


首先作为服务器端的代码:

package com.socket.myu;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.ServerSocket;import java.net.Socket;public class NetServer {public static void main(String[] args) throws IOException {// TODO Auto-generated method stubServerSocket ss = new ServerSocket(55554);System.out.println(ss.getLocalSocketAddress());while (true) {Socket socket = ss.accept();InputStream inputStream = socket.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream);BufferedReader bufferedReader = new BufferedReader(inputStreamReader);System.out.println(bufferedReader.readLine());OutputStream outputStream = socket.getOutputStream();OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);bufferedWriter.write("myu\n");bufferedWriter.flush();System.out.println("-----------------");inputStream.close();outputStream.close();socket.close();}}}
这段代码表示我们在55554端口中进行网络监听。

初学者可能会认为这里一直在进行while循环会导致进程一直占有CPU。这里不用担心,因为accept()方法会导致进程阻塞。什么意思呢?假如我们正在这个端口监听网络,但此时并没有任何客户端请求这个端口。此时进程就会进入阻塞状态(进程有三态),并让出CPU资源。

appcet()方法有什么作用呢?其作用是等待客户端连接XXX端口。


这里又引出另外一个知识点。JAVA I/O知识点中,InputStream和OutputStream表示的输入流和输出流(其都是以内存为中心点),都是字节流。而InputStreamReader、BufferedReader这些都是字符流。在JAVA中程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。

Reader类(字符流)的read()方法返回类型为int :作为整数读取的字符(占两个字节共16位),范围在 0 到 65535 之间 (0x00-0xffff),如果已到达流的末尾,则返回 -1
inputStream类(字节流)的read()虽然也返回int,但由于此类是面向字节流的,一个字节占8个位,所以返回 0 到 255 范围内的 int 字节值。如果因为已经到达流末尾而没有可用的字节,则返回值 -1。因此对于不能用0-255来表示的值就得用字符流来读取!比如说汉字.

所以输入或输出时,我们通常需要把字节流转换成字符流这点需要注意。


Android客户端APP:

package com.example.netserver2android;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.Socket;import android.os.Bundle;import android.app.Activity;import android.util.Log;import android.widget.TextView;public class MainActivity extends Activity {private TextView textView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);textView = (TextView) findViewById(R.id.textView1);MyThread myThread = new MyThread();Thread thread = new Thread(myThread);thread.start();}public class MyThread implements Runnable {@Overridepublic void run() {// TODO Auto-generated method stubtry {Log.v("123", "ready socket !!!");Socket socket = new Socket("192.168.1.147", 55554);Log.v("123", "-->" + socket.getInetAddress().getHostAddress());OutputStream outputStream = socket.getOutputStream();InputStream inputStream = socket.getInputStream();OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);bufferedWriter.write("Hello world!!!\n");bufferedWriter.flush();InputStreamReader inputStreamReader = new InputStreamReader(inputStream);BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String test;test = bufferedReader.readLine();textView.setText(test);outputStream.close();inputStream.close();socket.close();} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}}}

同时,在AndroidManifest.xmk中添加网络权限:

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


大家请注意代码中bufferedWriter.write("Hello world!!!\n");这句话。

这里之前我犯了一个致命的问题导致服务器端一直停滞在System.out.println(bufferedReader.readLine());。我之前是bufferedWriter.write("Hello world!!!");这样写的。

经过查询得知readLine()也是阻塞的。

String java.io.BufferedReader.readLine() throws IOExceptionReturns the next line of text available from this reader. A line is represented by zero or more characters followed by '\n', '\r', "\r\n" or the end of the reader. The string does not include the newline sequence.Returns:the contents of the line or null if no characters were read before the end of the reader has been reached.Throws:IOException - if this reader is closed or some other I/O error occurs.
这段是readLine()方法的解释,可以看到该方法是读取一行数据直到遇到\n、\r、\r\n结束符才会返回,否则程序就一直阻塞在这里不会向下运行。


0 0
原创粉丝点击