经过一段时间的Android开发学习,本着学习的心态,再网上找了一个资源,做了一个TCP/IP 的调试助手,主要涉及socket通信。最后,由于感觉一个手机界面太过难看,用了现在网上用的普遍的方法,导入SlidingMenu-master包,做了个手机侧滑界面。总之,类似一些电脑上的串口调试助手,有数据发送区和数据接收区,主要有TCP客户端和TCP服务端两种模式。
程序大体流程:
1.在侧滑界面,由用户选择把手机作为连接模式,有“TCP客户端模式”和“TCP服务器模式”两种模式选择;
2.对应不同的模式,分配不同的功能
a.服务器模式:界面信息显示本地IP,可自行设置端口号,点击开启服务器按钮,开启TCP_service连接线程,启动serversocket,进行监听,当有客户端socket连接时,开启连接线程,进行数据的交互。
b.客户端模式:用户设置所要连接的服务器的IP地址和端口号,点击连接,开启连接线程,连接成功后,进行与木目标服务器的数据交互。
3.本demo还对交互数据进行了处理,可分为十六进制显示和ascll显示。加了一些自动自动发送,自动换行等的功能。
本项目所用的权限:
由于用到WIFI连接,以及IP的地址获取,要配置相应的权限:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
上代码的讲解吧:
首先是客户端的连接线程:Tcp_Client
代码如下:
package com.loumeng.TCP; import android.os.Handler; import android.os.Message; import android.util.Log; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; /** * Created by Administrator on 2017/2/15. */ public class TCP_client extends Thread{ private static final String TAG_1 = "TCPChat"; private Handler mhandler; private Socket socket; private boolean isruning; public InputStream inputStream; public OutputStream outputStream; private InetAddress inetAddress; //IP地址 private int port; //端口号 public static int CLIENT_STATE_CORRECT_READ=7; public static int CLIENT_STATE_CORRECT_WRITE=8; //正常通信信息 public static int CLIENT_STATE_ERROR=9; //发生错误异常信息 public static int CLIENT_STATE_IOFO=10; //发送SOCKET信息 public TCP_client(Handler mhandler) { this.mhandler=mhandler; //传递handler对象用于与主线程的信息交互 isruning=true; } public void setInetAddress(InetAddress inetAddress) { this.inetAddress = inetAddress; } public void setPort(int port) { this.port = port; } @Override public void run() { if(socket == null){ try { Log.e(TAG_1,"启动连接线程"); socket=new Socket(inetAddress,port); new Receive_Thread(socket).start(); //启动接收线程 getadress(); } catch (IOException e) { e.printStackTrace(); senderror(); } } } public void getadress() //获取本地的IP地址和端口号
{ String[] strings = new String[2]; strings[0]=socket.getInetAddress().getHostAddress(); strings[1]=socket.getInetAddress().getHostName(); Message message = mhandler.obtainMessage(CLIENT_STATE_IOFO,-1,-1,strings); mhandler.sendMessage(message); } public void close(){ if (socket !=null){ try { socket.close(); socket=null; isruning=false; } catch (IOException e) { } }else if (socket ==null){ Log.e(TAG_1, "未建立连接"); } } class Receive_Thread extends Thread{ private Socket msocket; public Receive_Thread (Socket msocket){ this.msocket =msocket; } @Override public void run() { try { while (isruning) { inputStream = msocket.getInputStream(); while (inputStream.available()==0){ } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } final byte[] buffer = new byte[1024];//创建接收缓冲区 final int len = inputStream.read(buffer);//数据读出来,并且数据的长度 mhandler.sendMessage(mhandler. obtainMessage(CLIENT_STATE_CORRECT_READ,len,-1,buffer)); } }catch (IOException e) { e.printStackTrace(); senderror(); }finally { if(msocket!=null){ try { msocket.close(); } catch (IOException e) { e.printStackTrace(); } } try { if(inputStream!=null){ inputStream.close(); } if (outputStream!=null){ outputStream.close(); } } catch (IOException e) { e.printStackTrace(); } Log.e(TAG_1,"关闭连接,释放资源"); } } } public void sendmessage(byte[] message){ try { outputStream =socket.getOutputStream(); mhandler.sendMessage(mhandler. obtainMessage(CLIENT_STATE_CORRECT_WRITE,-1,-1,message)); outputStream.write(message); } catch (IOException e) { senderror(); } } void senderror(){ mhandler.sendMessage(mhandler.obtainMessage(CLIENT_STATE_ERROR)); //发送连接的错误 } }
接下来是服务器端的连接子线程 TCP_serveice.class
代码如下:
package com.loumeng.TCP; import android.os.Handler; import android.os.Message; import android.util.Log; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; /** * Created by Administrator on 2017/2/13. */ public class TCP_service extends Thread{ private static final String TAG_1 = "TCPChat"; private Handler mhandler; private ServerSocket serverSocket; public InputStream Ser_inputStream; public OutputStream Ser_outputStream; private Socket Ser_Socket; private int mport; private boolean is_start =true; public static int SERVER_STATE_CORRECT_READ=3; public static int SERVER_STATE_CORRECT_WRITE=4; //正常通信信息 public static int SERVER_STATE_ERROR=5; //发生错误异常信息 public static int SERVER_STATE_IOFO=6; //发送SOCKET信息 public TCP_service(Handler mhandler,int mport){ this.mhandler=mhandler; this.mport=mport; } @Override public void run() { super.run(); try { serverSocket= new ServerSocket(mport); } catch (IOException e) { e.printStackTrace(); send_Error(); } try { while (is_start) { Log.e(TAG_1,"等待客户端连接 is_start="+ is_start); Ser_Socket=serverSocket.accept(); //开启监听 if(Ser_Socket!=null){ //启动接收线程 Receive_Thread receive_Thread = new Receive_Thread(Ser_Socket); //当有客户端连接时,开启数据接收的线程 receive_Thread.start(); } } }catch (IOException e) { e.printStackTrace(); send_Error(); // 发送错误
} } class Receive_Thread extends Thread { private Socket socket = null; public Receive_Thread(Socket socket) { this.socket = socket; getAddress(); try { Ser_inputStream = socket.getInputStream(); Ser_outputStream = socket.getOutputStream(); } catch (IOException e) { e.printStackTrace(); send_Error(); } } public void getAddress() { InetAddress inetAddress = socket.getInetAddress(); String[] strings = new String[2]; strings[0] = inetAddress.getHostAddress(); strings[1] = inetAddress.getHostName(); Message message = mhandler.obtainMessage(SERVER_STATE_IOFO, strings); mhandler.sendMessage(message); } @Override public void run() { super.run(); while (is_start) { try { while (Ser_inputStream.available() == 0) { } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } final byte[] buf = new byte[1024]; final int len = Ser_inputStream.read(buf); Message message = mhandler.obtainMessage(SERVER_STATE_CORRECT_READ, len, 1, buf); mhandler.sendMessage(message); } catch (IOException e) { e.printStackTrace(); send_Error(); } } try { if (Ser_inputStream != null) Ser_inputStream.close(); if (Ser_outputStream != null) Ser_outputStream.close(); if (socket != null) { socket.close(); socket = null; } Log.e(TAG_1, "断开连接监听 释放资源"); } catch (IOException e) { e.printStackTrace(); } } } public void close() { try { if (serverSocket != null) serverSocket.close(); if (Ser_Socket != null) Ser_Socket.close(); Log.e(TAG_1, "断开连接监听 关闭监听SOCKET"); } catch (IOException e) { e.printStackTrace(); } } //数据写入函数 public void write(byte[] buffer){ try { if (Ser_outputStream!=null){ Ser_outputStream.write(buffer); Message er_message = mhandler. obtainMessage(SERVER_STATE_CORRECT_WRITE,-1,-1,buffer); mhandler.sendMessage(er_message); }else{ send_Error();} } catch (IOException e) { e.printStackTrace(); send_Error(); } } public void send_Error(){ Message er_message = mhandler.obtainMessage(SERVER_STATE_ERROR); mhandler.sendMessage(er_message); } public void setis_start(boolean is_start) { this.is_start = is_start; } }主界面的主程序:TCP_chat.class,主要是对以上两个子线程的调用和对数据的交互和处理。
代码如下:
package com.loumeng.activity; import android.app.Activity; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.view.View; import android.view.Window; import android.widget.AdapterView; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu; import com.loumeng.Bluetooth.R; import com.loumeng.TCP.Data_syn; import com.loumeng.TCP.TCP_client; import com.loumeng.TCP.TCP_service; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.UnknownHostException; /** * Created by Administrator on 2017/1/12. */ public class TCPchat extends Activity { private static final String TAG_1 = "TCPChat"; //控件按钮 private Button start; private Button stop; private Button clear_; private Button send; //复选按钮控件 private CheckBox hex_show; private CheckBox auto_huang; private CheckBox hex_send; private CheckBox auto_send; //文本显示控件 private TextView ip_mode; private TextView port_mode; private TextView de_state; //设置状态 private TextView ip_show; //连接的对象IP 显示 private TextView name_show; //连接的对象主机名号 显示 private TextView re_count; //接收字节数 private TextView se_count; //发送字节数 private TextView re_data_show; //接收字节显示 //编辑框控件 private EditText edit_ip; private EditText edit_port; private EditText edit_time; private EditText edit_data; //下拉控件 private Spinner link_mode; //连接模式 // private boolean exit; //网络连接模式选择 public final static int MODE_TCP_SERVER=0; public final static int MODE_TCP_CLIENT=1; public final static int MODE_UDP=2; private int ch_mode=0; //TCP服务器通信模式下 private TCP_service tcp_service =null; private int ser_port; private boolean ser_islink=false; public final static int SERVER_STATE_CORRECT_READ=3; public final static int SERVER_STATE_CORRECT_WRITE=4; //正常通信信息 public final static int SERVER_STATE_ERROR=5; //发生错误异常信息 public final static int SERVER_STATE_IOFO=6; //发送SOCKET信息 // TCP客户端通信模式下 private TCP_client tcp_client =null; private final static int CLIENT_STATE_CORRECT_READ=7; public final static int CLIENT_STATE_CORRECT_WRITE=8; //正常通信信息 public final static int CLIENT_STATE_ERROR=9; //发生错误异常信息 public final static int CLIENT_STATE_IOFO=10; //发送SOCKET信息 private boolean client_islink =false; //复选状态信息 private boolean Hex_show =false; private boolean Auto_huang =false; private boolean Hex_send =false; private boolean Auto_send =false; //计数用 private int countin =0; private int countout=0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.ly_tcpchat); SlidingMenuinit(); //侧滑菜单初始化 init(); link_mode.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { ch_mode = position; if (ch_mode == MODE_TCP_SERVER) { ip_mode.setText("本地 I P"); port_mode.setText("本地端口"); start.setText("启动"); de_state.setText(""); ip_show.setHint("对象IP"); name_show.setHint("对象主机名"); clear(); } if (ch_mode == MODE_TCP_CLIENT) { ip_mode.setText("目的 I P"); port_mode.setText("目的端口"); start.setText("连接"); de_state.setText(""); ip_show.setHint("对象IP"); name_show.setHint("对象主机名"); clear(); } } @Override public void onNothingSelected(AdapterView<?> parent) { } }); edit_ip.setText(getLocalIpAddress()); //获取本地IP地址显示 edit_port.setText(8080+""); //设置默认端口号 start.setOnClickListener(startlistener); stop.setOnClickListener(stoplistener); send.setOnClickListener(sendlistener); clear_.setOnClickListener(clearlistener); hex_send.setOnCheckedChangeListener(listener); hex_show.setOnCheckedChangeListener(listener); auto_huang.setOnCheckedChangeListener(listener); auto_send.setOnCheckedChangeListener(listener); } //初始化控件函数 private void init() { link_mode= (Spinner) findViewById(R.id.ch_mode); ip_mode= (TextView) findViewById(R.id.ip_mode); port_mode= (TextView) findViewById(R.id.port_mode); start= (Button) findViewById(R.id.start); stop= (Button) findViewById(R.id.stop); clear_= (Button) findViewById(R.id.de_clear); send= (Button) findViewById(R.id.de_send); de_state= (TextView) findViewById(R.id.de_action); ip_show= (TextView) findViewById(R.id.de_ip); name_show= (TextView) findViewById(R.id.de_sport); re_count= (TextView) findViewById(R.id.receive_count); se_count= (TextView) findViewById(R.id.send_count); re_data_show= (TextView) findViewById(R.id.receive); re_data_show.setMovementMethod(ScrollingMovementMethod .getInstance());// 使TextView接收区可以滚动 edit_ip= (EditText) findViewById(R.id.ip_edit); edit_port= (EditText) findViewById(R.id.port_edit); edit_time= (EditText) findViewById(R.id.edi_auto); edit_data= (EditText) findViewById(R.id.send_data); hex_show= (CheckBox) findViewById(R.id.hex_show); auto_huang= (CheckBox) findViewById(R.id.autohuang); hex_send= (CheckBox) findViewById(R.id.hex_send); auto_send= (CheckBox) findViewById(R.id.auto_send); } private OnCheckedChangeListener listener =new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (buttonView.getId()){ case R.id.hex_show: if (isChecked) { Toast.makeText(TCPchat.this, "16进制显示", Toast.LENGTH_SHORT).show(); Hex_show = true; } else Hex_show = false; break; case R.id.autohuang: if (isChecked) { Toast.makeText(TCPchat.this, "自动换行", Toast.LENGTH_SHORT).show(); Auto_huang = true; } else Auto_huang = false; break; case R.id.hex_send: if (isChecked) { Toast.makeText(TCPchat.this, "16进制发送", Toast.LENGTH_SHORT).show(); Hex_send = true; } else Hex_send = false; break; case R.id.auto_send: if (isChecked) { Toast.makeText(TCPchat.this, "16进制发送", Toast.LENGTH_SHORT).show(); Auto_send = true; } else Auto_send = false; break; } } }; private View.OnClickListener startlistener= new View.OnClickListener() { @Override public void onClick(View v) { if (ch_mode==MODE_TCP_SERVER){ if(tcp_service == null){ ser_port=Integer.valueOf(edit_port.getText().toString()); //获取设置的端口号 默认8080 tcp_service =new TCP_service(ser_handler,ser_port); tcp_service.start(); de_state.setText("TCP服务器模式 启动"); stop.setEnabled(true); edit_ip.setEnabled(false); edit_port.setEnabled(false); } else{ Log.e(TAG_1, "断开连接监听 释放资源"); de_state.setText("TCP服务器模式 出错"); } } if(ch_mode==MODE_TCP_CLIENT){ if(tcp_client == null) { tcp_client =new TCP_client(cli_handler); try { InetAddress ipAddress = InetAddress.getByName (edit_ip.getText().toString()); int port =Integer.valueOf(edit_port.getText().toString());//获取端口号 tcp_client.setInetAddress(ipAddress); tcp_client.setPort(port); } catch (UnknownHostException e) { e.printStackTrace(); } edit_ip.setEnabled(false); edit_port.setEnabled(false); tcp_client.start(); } stop.setEnabled(true); } } }; private View.OnClickListener clearlistener=new View.OnClickListener() { @Override public void onClick(View v) { clear(); } }; private View.OnClickListener stoplistener= new View.OnClickListener() { @Override public void onClick(View v) { if (ch_mode==MODE_TCP_SERVER){ tcp_service.setis_start(false); if(tcp_service!=null) { tcp_service.close(); tcp_service=null; } de_state.setText("TCP服务器模式 关闭"); Ip_clear(); edit_ip.setEnabled(true); edit_port.setEnabled(true); } if(ch_mode == MODE_TCP_CLIENT){ if(tcp_client != null){ tcp_client.close(); tcp_client=null; } Ip_clear(); edit_ip.setEnabled(true); edit_port.setEnabled(true); stop.setEnabled(false); } } }; //发送响应函数 private View.OnClickListener sendlistener= new View.OnClickListener() { @Override public void onClick(View v) { if (ch_mode==MODE_TCP_SERVER){ if(ser_islink==true){ String message= edit_data.getText().toString().replaceAll(" ",""); if(message.equals("")){ Toast.makeText(TCPchat.this,"发送内容不能为空", Toast.LENGTH_SHORT).show(); } sendmessage(message); }else{ Toast.makeText(TCPchat.this,"连接未建立", Toast.LENGTH_SHORT).show(); } } if (ch_mode==MODE_TCP_CLIENT){ if(client_islink==true){ String message= edit_data.getText().toString().replaceAll(" ",""); if(message.equals("")){ Toast.makeText(TCPchat.this,"发送内容不能为空", Toast.LENGTH_SHORT).show(); } sendmessage(message); }else{ Toast.makeText(TCPchat.this,"连接未建立", Toast.LENGTH_SHORT).show(); } } } }; @Override protected void onDestroy(){ super.onDestroy(); if(tcp_service!=null) { tcp_service.setis_start(false); tcp_service.close(); tcp_service=null; } if(tcp_client != null){ tcp_client.close(); tcp_client=null; } } private void SlidingMenuinit() //侧滑界面初始化函数,网上的列子很多,架包配置Android studio,网上有大量的教程
{ SlidingMenu menu = new SlidingMenu(this); menu.setMode(SlidingMenu.LEFT); // 设置触摸屏幕的模式 menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN); menu.setShadowWidthRes(R.dimen.shadow_width); menu.setShadowDrawable(R.drawable.shadow); // 设置滑动菜单视图的宽度 menu.setBehindOffsetRes(R.dimen.slidingmenu_offset); // 设置渐入渐出效果的值 menu.setFadeDegree(0.35f); //把滑动菜单添加进所有的Activity中,可选值SLIDING_CONTENT , SLIDING_WINDOW menu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT); //为侧滑菜单设置布局 menu.setMenu(R.layout.ly_tcpchat_left); } private Handler ser_handler =new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if(msg.what==SERVER_STATE_ERROR){ Toast.makeText(TCPchat.this,"连接异常" ,Toast.LENGTH_SHORT).show(); de_state.setText("TCP服务器模式 连接异常"); ip_show.setHint("对象IP"); name_show.setHint("对象主机名"); ser_islink=false; } //发送数据 if (msg.what==SERVER_STATE_CORRECT_WRITE){ Handler_send(msg); } //接收数据 if(msg.what==SERVER_STATE_CORRECT_READ){ Handler_receive(msg); } if(msg.what==SERVER_STATE_IOFO){ ser_islink=true; de_state.setText("TCP服务器模式 建立连接"); stop.setEnabled(true); String[] strings= (String[]) msg.obj; ip_show.append(strings[0]+"\n"); name_show.append(strings[1]+"\n"); } } }; //客户端通信模式下 private Handler cli_handler =new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch( msg.what){ case CLIENT_STATE_ERROR : Toast.makeText(TCPchat.this,"连接异常" ,Toast.LENGTH_SHORT).show(); de_state.setText("TCP客户端模式 连接异常"); ip_show.setHint("对象IP"); name_show.setHint("对象主机名"); client_islink=false; break; case CLIENT_STATE_IOFO : client_islink =true; de_state.setText("TCP客户端模式 建立连接"); String[] strings= (String[]) msg.obj; ip_show.append(strings[0]+"\n"); name_show.append(strings[1]+"\n"); break; //接收数据 case CLIENT_STATE_CORRECT_READ : Handler_receive(msg); break; //发送数据 case CLIENT_STATE_CORRECT_WRITE: Handler_send(msg); break; } } }; @Override public void onBackPressed() { exit(); } //获取wifi本地IP和主机名 private String getLocalIpAddress() { WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); // 获取32位整型IP地址 int ipAddress = wifiInfo.getIpAddress(); //返回整型地址转换成“*.*.*.*”地址 return String.format("%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff), (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff)); } //发送数据函数 public void sendmessage(String message){ if(Hex_send == true){ byte[] send = Data_syn.hexStr2Bytes(message); if(ch_mode==MODE_TCP_SERVER) { tcp_service.write(send); }else if (ch_mode==MODE_TCP_CLIENT){ tcp_client.sendmessage(send); } }else{ byte[] send = message.getBytes(); if(ch_mode==MODE_TCP_SERVER) { tcp_service.write(send); }else if (ch_mode==MODE_TCP_CLIENT){ tcp_client.sendmessage(send); } } } //页面退出函数 public void exit(){ if(exit == true){ this.finish(); } exit = true; Toast.makeText(this,"再按一次,返回上一页",Toast.LENGTH_SHORT).show(); } //定时返回函数 private Runnable runnable = new Runnable() { @Override public void run() { String message = edit_data.getText().toString(); sendmessage(message); } }; //清除函数 private void clear() { countin=0; countout=0; re_count.setText("0个"); se_count.setText("0个"); re_data_show.setText(""); } // 接收数据处理分析函数,通过handler从子线程回传到主线程 private void Handler_receive(Message msg){ byte[] buffer= (byte[]) msg.obj; if (Hex_show == true) { String readMessage = " " + Data_syn.bytesToHexString(buffer, msg.arg1); re_data_show.append(readMessage); if(Auto_huang==true){ re_data_show.append("\n"); } countin += readMessage.length() / 2; // 接收计数 re_count.setText("" + countin+"个"); } else if (Hex_show == false) { String readMessage = null; try { readMessage = new String(buffer, 0, msg.arg1, "GBK"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } re_data_show.append(readMessage); if(Auto_huang==true){ re_data_show.append("\n"); } countin += readMessage.length(); // 接收计数 re_count.setText("" + countin+"个"); } } //发送数据处理分析函数,通过handler从子线程回传主线程 private void Handler_send(Message msg){ byte[] writeBuf = (byte[]) msg.obj; if (Auto_send == true) { String s = edit_time.getText().toString(); long t = Long.parseLong(s); ser_handler.postDelayed(runnable, t); } else if (Auto_send == false) { ser_handler.removeCallbacks(runnable); } if (Hex_send == true) { String writeMessage = Data_syn.Bytes2HexString(writeBuf); countout += writeMessage.length() / 2; se_count.setText("" + countout+"个"); } else if (Hex_send == false) { String writeMessage = null; try { writeMessage = new String(writeBuf, "GBK"); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } countout += writeMessage.length(); se_count.setText("" + countout+"个"); } } //目的地址和目的主机名清空函数 private void Ip_clear(){ ip_show.setText(""); name_show.setText(""); } }
代码比较多,本人也是新手,可能有部分代码不怎么科学合理,但总体经过测试可用,主要函数代码都有一定的注释,相信各位也看的懂得啦。
接下来是数据处理的代码,涉及十六进制和ascll数据的转化
代码如下:
package com.loumeng.TCP; public class Data_syn { // 将字节数组转化为16进制字符串,确定长度 public static String bytesToHexString(byte[] bytes, int a) { String result = ""; for (int i = 0; i < a; i++) { String hexString = Integer.toHexString(bytes[i] & 0xFF);// 将高24位置0 if (hexString.length() == 1) { hexString = '0' + hexString; } result += hexString.toUpperCase(); } return result; } // 将字节数组转化为16进制字符串,不确定长度 public static String Bytes2HexString(byte[] b) { String ret = ""; for (int i =0; i < b.length; i++) { String hex = Integer.toHexString(b[i] & 0xFF);// 将高24位置0 if (hex.length() == 1) { hex = '0' + hex; } ret += hex.toUpperCase(); } return ret; } // 将16进制字符串转化为字节数组 public static byte[] hexStr2Bytes(String paramString) { int i = paramString.length() / 2; byte[] arrayOfByte = new byte[i]; int j = 0; while (true) { if (j >= i) return arrayOfByte; int k = 1 + j * 2; int l = k + 1; arrayOfByte[j] = (byte) (0xFF & Integer.decode( "0x" + paramString.substring(j * 2, k) + paramString.substring(k, l)).intValue()); ++j; } } }
主界面布局 文件ly_tcpchat.xml文件
ly_tcpchat_left.xml 布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:weightSum="1" android:background="#CDAA7D35"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:textColor="#000000" android:text="@string/link_"/> <TextView android:id="@+id/de_action" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#000000" android:textSize="15sp" android:hint="@string/de_state"/> </LinearLayout> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" > <TextView android:id="@+id/de_ip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="15sp" android:hint="@string/d_ip" android:textColor="#1C1C1C" /> <TextView android:id="@+id/de_sport" android:layout_alignParentRight="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="15sp" android:textColor="#1C1C1C" android:hint="@string/d_port"/> </RelativeLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/re_data" android:textSize="20sp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/re_count" android:layout_marginLeft="100dp" android:textSize="15sp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="@string/_0" android:id="@+id/receive_count" android:textSize="15sp"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.6" android:background="#EED5D2"> <TextView android:id="@+id/receive" android:layout_width="match_parent" android:layout_height="200dp" android:background="#EED5D2" android:textColor="#2F4F4F" android:textSize="20sp"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:text="@string/se_data"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/send_count" android:layout_marginLeft="100dp" android:textSize="15sp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="@string/_0" android:id="@+id/send_count" android:textSize="15sp"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.4"> <EditText android:id="@+id/send_data" android:layout_width="match_parent" android:layout_height="180dp" android:textSize="25sp" android:textColor="#2F4F4F" android:background="#EED5D2"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:weightSum="1"> <Button android:id="@+id/de_clear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="0.4" android:layout_marginBottom="20dp" android:text="@string/de_clear"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/de_send" android:layout_marginBottom="20dp" android:layout_marginLeft="5dp" android:layout_weight="0.4" android:text="@string/de_send"/> </LinearLayout> </LinearLayout>
ly_tcpchat_left.xml 布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@drawable/b_kuan"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="@string/set" android:textSize="25sp" android:layout_gravity="center" android:textColor="#000000"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/li_mode" android:layout_gravity="center_vertical" android:layout_marginLeft="30dp" android:textSize="15sp" android:textColor="#2F4F4F"/> <Spinner android:id="@+id/ch_mode" android:layout_width="150dp" android:layout_height="30dp" android:entries="@array/mode" android:layout_gravity="center_horizontal" android:spinnerMode="dialog"> </Spinner> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="1dp" > <TextView android:id="@+id/ip_mode" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/de_ip" android:layout_gravity="center_vertical" android:layout_marginLeft="30dp" android:textSize="15sp" android:textColor="#2F4F4F"/> <EditText android:id="@+id/ip_edit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textSize="15sp" android:textColor="#696969" android:layout_marginLeft="15dp" android:hint="@string/ip"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="1dp" > <TextView android:id="@+id/port_mode" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="30dp" android:layout_gravity="center_vertical" android:text="@string/de_poet" android:textSize="15sp" android:textColor="#2F4F4F"/> <EditText android:id="@+id/port_edit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textSize="13sp" android:textColor="#696969" android:layout_marginLeft="15dp" android:hint="@string/port"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="1dp" android:gravity="center" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/start" android:textSize="15sp" android:text="@string/start"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/stop" android:textSize="15sp" android:layout_marginLeft="5dp" android:enabled="false" android:text="@string/out"/> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="25dp" android:text="@string/re_set" android:textSize="25sp" android:layout_gravity="center" android:textColor="#000000"/> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hex_show" android:layout_marginLeft="30dp" android:layout_marginTop="20dp" android:textColor="#2F4F4F" android:id="@+id/hex_show" android:textSize="15sp" android:checked="false" /> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/auto_huan" android:textSize="15sp" android:layout_marginTop="10dp" android:textColor="#2F4F4F" android:id="@+id/autohuang" android:layout_marginLeft="30dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="45dp" android:text="@string/send_set" android:textSize="25sp" android:layout_gravity="center" android:textColor="#000000"/> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hex_send" android:textSize="15sp" android:layout_marginTop="10dp" android:textColor="#2F4F4F" android:id="@+id/hex_send" android:layout_marginLeft="30dp" android:checked="false" /> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/auto_send" android:textSize="15sp" android:layout_marginTop="1dp" android:textColor="#2F4F4F" android:id="@+id/auto_send" android:layout_marginLeft="30dp"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="45dp" android:textColor="#2F4F4F" android:textSize="15sp" android:text="@string/time"/> <EditText android:id="@+id/edi_auto" android:layout_width="50dp" android:layout_marginLeft="10dp" android:layout_height="match_parent" android:background="#ffffffff" android:ems="10" android:hint="@string/edtauto" android:inputType="number" android:textColor="#ff000000" android:textSize="18sp" /> </LinearLayout> </LinearLayout>
项目Demo的效果截图如下:
总结:
这个项目总的来说是比较简单的,解释涉及Java socket的通信,不管是作为服务器或者客户端,都是socket在通信。侧滑界面的设置和使用,网上资料很多,这这里就不一一解释说明了。代码上去弄得比较繁琐,学习做的东西,还请各位请见谅,有什么意见和想法,欢迎留言,一起共同努力。