经过一段时间的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;
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();
}
}
}
{
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){
new Thread(){
@Override
public void run() {
super.run();
try {
outputStream =socket.getOutputStream();
mhandler.sendMessage(mhandler.
obtainMessage(CLIENT_STATE_CORRECT_WRITE,-1,-1,message));
outputStream.write(message);
} catch (IOException e) {
senderror();
}
}
}.start();
}
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){
new Thread(){
@Override
public void run() {
super.run();
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();
}
}
}.start();
}
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在通信。侧滑界面的设置和使用,网上资料很多,这这里就不一一解释说明了。代码上去弄得比较繁琐,学习做的东西,还请各位请见谅,有什么意见和想法,欢迎留言,一起共同努力。