Android-socket-client 客户端实现

               

—————————————————————————————————————————————————————————————————————————————

开发环境:eclipse  +4.0android SDK+串口调试工具


前言:这周的任务是为了 完成socket客户端在安卓平台的开发,能够和服务端正常进行收发信息(还未实现汉字)。开始在网上找了很多程序用来参考,结果都不行,发现android3.0以后就不能在主线程(ui线程)中进行socket网络通信!!看来找的程序比较老了,后来有幸找到了极客学院的一个视频,按照上面的方法直接实现了一下,它的比较简单,所以我又稍微优化了一下,而且它的程序还是有一点小bug的,我修改了一下,不过还有待加强。


ps:模拟器和手机上都能成功运行


首先附上极客学院的视频地址:http://www.iqiyi.com/w_19rtlpgvl1.html


效果图片:

客户端(界面)


服务端:(串口调试助手)


正常通信


超时,即socket连接不上



极客学院中的视频的小bug就是在doInBackground中使用了toast,这个应该是不允许的。

还有就是它的代码中用到了异步通信AsyncTask,我遇到的困难都是因为对它不了解,导致出了很多低级的错误,浪费了我很多的时间,给大家一个链接可以学习一下。

自己的错误也在代码中进行了注释,希望能帮助到大家。

大家可以参考这个链接学习  http://www.cnblogs.com/devinzhang/archive/2012/02/13/2350070.html


自己代码的小特色:

1.可以自己手动输入ip地址和端口号,特别是端口号我们是需要获取数字的,所以这里用了一个Integer.parseInt的方法,当然还增加了一个断开连接。

2.利用了socket.connect这个接口,来判断socket是否连接超时,即服务器连接不上,错误的原因有很多,ip不对啊,端口不对,服务器关闭等等。


个人感觉 android socket客户端的操作流程大致是:

1.首先new 一个socket,然后用ip和端口去初始化它。

2.然后初始化它的outputstream和inputstream,输入输出流,当客户端发数据是操作它的输出流,接受数据是操作它的输入流,将他们放入我们的buf中,最后再对buf进行操作。

ps:其实是比较简单,对我来说很难的应该就是语法吧,很多类的规则和方法不知道怎么去调用,特别是doinbackground中不能操作主线程中的控件和变量真是让我浪费了很久的时间。


附上代码:

代码中我作了一点注释

package com.lzj.example.msocketclient;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.net.InetSocketAddress;import java.net.Socket;import android.app.Activity;import android.os.AsyncTask;import android.os.Bundle;import android.text.method.ScrollingMovementMethod;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity {  private EditText ip=null,port=nullprivate EditText editTest=nullprivate TextView text=nullprivate Button   send_btn=null,con_btn=null,discon_btn=nullprivate int port_num=0protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_lmain);  ip=(EditText)findViewById(R.id.ip);  port=(EditText)findViewById(R.id.port);  editTest=(EditText)findViewById(R.id.editText);  text=(TextView)findViewById(R.id.textView);    text.setMovementMethod(ScrollingMovementMethod.getInstance());//使能textview滚动属性      con_btn=(Button)findViewById(R.id.con_btn);  con_btn.setOnClickListener(new OnClickListener() {   public void onClick(View v) {    connect();    send_btn.setEnabled(true);    editTest.setEnabled(true);              }  });     send_btn=(Button) findViewById(R.id.send_btn);  send_btn.setOnClickListener(new OnClickListener() {   public void onClick(View v) {    send();   }  });    discon_btn=(Button)findViewById(R.id.discon_btn);  discon_btn.setOnClickListener(new OnClickListener() {   public void onClick(View v) {    close();       }  });  send_btn.setEnabled(false);  editTest.setEnabled(false); }   //-------------socket  实现--------------------------  Socket socket=null; BufferedWriter bw=null; BufferedReader br=null;  /*android4.0后不能在主线程(UI线程)中初始化socket,进行socket网络通信,所以我们用asynctask(异步)来将这个过程放到后台*/ public void connect(){    AsyncTask<Void, String, Void> read=new AsyncTask<Void, String, Void>(){   /*doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。   * 在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。*/  protected Void doInBackground(Void... arg0) {//doinbackground该方法中不能对UI当中的空间进行设置和修改                               //将输入端口的editText中获取的string转化为int    port_num=Integer.parseInt(port.getText().toString().trim());     /*字节流转换成字符流可以用 InputSteamReader  OutputStreamWriter         转换成BufferdReader  BufferedWriter 他们具有缓冲区   */    socket=new Socket();    String line;      //用connect延时3秒来看客户端是否连接服务器    try {      socket.connect(new InetSocketAddress(ip.getText().toString(),port_num ),3000);      bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));        br=new BufferedReader(new InputStreamReader(socket.getInputStream()));      publishProgress("@连接成功");     //readline是以\n结尾,所以send函数中的write方法中需要加+\n      /*这个地方是我出错的地方,只是把上面3句用try catch包围!当第一次输入错误ip的时候       * 程序会退出,是因为我把下面这个循环用try catch包围了,因为下面用到了br变量       * 如果前面出错那么这个变量则不会被初始化!!       * 同样不能再catch中用toast,因为不能在非ui线程中使用它,doinbackground是在后台运行       * 切记!花了我太久太久的时间了!*/      while ((line=br.readLine())!=null){       publishProgress(line);      }     } catch (IOException e1) {      try {//异常检查,如果超时或者断开连接则则执行下面操作       publishProgress("@连接失败(超时or断开)");       socket.close();      } catch (IOException e) {       e.printStackTrace();      }      e1.printStackTrace();     }               return null;   }   /*onProgressUpdate(Progress…)       * 可以使用进度条增加用户体验度。    *  此方法在主线程执行,用于显示任务执行的进度。    *  这里是可以执行主线程中的设置,所以可以用toast*/ protected void onProgressUpdate(String... values) {  super.onProgressUpdate(values);    if(values[0].equals("@连接成功")){     Toast.makeText(MainActivity.this,"连接成功" ,Toast.LENGTH_SHORT).show();     }    text.append("服务器:"+values[0]+"\n");         }     };  read.execute();//执行 } /*发送信息的函数*/ public void send() {  try {   text.append("本机:"+editTest.getText().toString()+"\n");   bw.write(editTest.getText().toString()+"\n");   bw.flush();   editTest.setText("");  } catch (IOException e) {   e.printStackTrace();  }   } /*关闭socket函数,即断开连接*/ public void close(){  try {   socket.close();   Toast.makeText(MainActivity.this,"断开连接" ,Toast.LENGTH_SHORT).show();   send_btn.setEnabled(false);   editTest.setEnabled(false);  } catch (IOException e) {   e.printStackTrace();  }   }}

xml文件:

<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:background="@drawable/bk"    tools:context="${relativePackage}.${activityClass}"     >    <EditText        android:id="@+id/ip"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignBottom="@+id/con_btn"        android:layout_alignParentLeft="true"        android:layout_alignParentTop="true"        android:layout_toLeftOf="@+id/con_btn"        android:hint="请输入服务器ip地址"  android:textColorHint="#ffff"        android:ems="10" />    <EditText        android:id="@+id/editText"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:layout_alignParentLeft="true"        android:layout_alignParentRight="true"        android:layout_marginBottom="70dp"        android:hint="编辑内容"        android:textColorHint="#0000"        android:ems="10" >        <requestFocus />    </EditText>       <Button        android:id="@+id/send_btn"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:layout_alignParentLeft="true"        android:layout_alignParentRight="true"        android:layout_marginBottom="28dp"        android:text="发送"         android:textStyle="bold"        />    <Button        android:id="@+id/con_btn"        style="?android:attr/buttonStyleSmall"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentTop="true"        android:layout_toLeftOf="@+id/discon_btn"        android:text="连接"         android:textStyle="bold"        />    <Button        android:id="@+id/discon_btn"        style="?android:attr/buttonStyleSmall"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignBottom="@+id/con_btn"        android:layout_alignParentRight="true"        android:layout_alignParentTop="true"        android:text="断开"        android:textStyle="bold"        />    <!-- 设置textview下拉属性 scrollbars  “滚动条出现到消失的时间=5000ms” -->    <TextView        android:id="@+id/textView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_above="@+id/editText"        android:layout_alignParentLeft="true"        android:layout_alignParentRight="true"        android:layout_below="@+id/port"        android:scrollbarFadeDuration="5000"        android:scrollbarStyle="insideOverlay"        android:scrollbars="vertical"        android:textColorHint="#ffff"        android:hint="聊天区域"/>    <EditText        android:id="@+id/port"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentLeft="true"        android:layout_below="@+id/ip"        android:layout_toLeftOf="@+id/con_btn"        android:ems="10"        android:hint="请输入服务器端口号"        android:textColorHint="#ffff"        android:inputType="number" /></RelativeLayout>


记得在AndroidManifest.xml中加上权限
<uses-permission android:name="android.permission.INTERNET"/>

下一篇地址: http://blog.csdn.net/liuzijiang1123/article/details/50365546




           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

猜你喜欢

转载自blog.csdn.net/qq_43682438/article/details/86371028