您的位置:首页 > 理论基础 > 计算机网络

【Android Socket专题】: TCP通信客户端app的demo的实现

2017-04-25 19:14 429 查看
UDP Client客户端  http://blog.csdn.net/shankezh/article/details/50731287

UDP Server服务器 http://blog.csdn.net/shankezh/article/details/51452811

TCP Client客户端  http://blog.csdn.net/shankezh/article/details/70763579

TCP Server服务器 http://blog.csdn.net/shankezh/article/details/51555455

-------

Android TCP 客户端实现,规划界面如下:



对应XML代码如下:

<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="5"
>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ip:"/>
<EditText
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="match_parent"
android:gravity="center"
android:id="@+id/edit_tcpClientIp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="port"/>

<EditText
android:id="@+id/edit_tcpClientPort"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
android:layout_weight="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ID(英文或数字):"/>
<EditText
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:id="@+id/edit_tcpClientID"/>
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="随机生成"
android:id="@+id/btn_tcpClientRandomID"/>
</LinearLayout>

</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>

<Button
android:id="@+id/btn_tcpClientConn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="连接" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="断开"
android:id="@+id/btn_tcpClientClose"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="清除接收区"
android:id="@+id/btn_tcpCleanClientRecv"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="清除发送区"
android:id="@+id/btn_tcpCleanClientSend"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:layout_weight="2">
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="bottom"
android:text="接收区:" />
<TextView
android:layout_width="match_parent"
android:layout_weight="5"
android:layout_height="0dp"
android:id="@+id/txt_ClientRcv"
android:background="@android:color/holo_blue_light"
/>

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:layout_weight="2">
<TextView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:text="发送区:" />

<TextView
android:id="@+id/txt_ClientSend"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="7"
android:background="@android:color/holo_purple" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
android:layout_weight="2">
<EditText
android:layout_width="0dp"
android:layout_weight="5"
android:id="@+id/edit_tcpClientSend"
android:layout_height="match_parent" />
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:layout_gravity="right"
android:id="@+id/btn_tcpClientSend"
android:text="发送"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>


界面完成,关键类点名(只点名,不解释,详细解释请使用搜索引擎,太占篇幅):

1、Socket;

2、PrintWriter;

3、InputStream;

4、DataInputStream;

以上是构建tcp客户端的关键类,需要明白。

客户端比服务器实现简单很多,下面是实现思路描述:

1、直接使用Socket类,通过ip和port创建连接;

2、创建接收与发送使用,超时等资源配置;

3、建立监听循环机制;

4、跳出循环,关闭连接。

发送消息则直接使用之前创建的发送资源推送即可,不做描述。

具体代码如下:

package jason.tcpdemo.coms;

import android.content.Intent;
import android.util.Log;

import java.io.BufferedReader;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import jason.tcpdemo.funcs.FuncTcpClient;
import jason.tcpdemo.funcs.FuncTcpServer;

/**
* Created by Jason Zhu on 2017-04-25.
*
*/

public class TcpClient implements Runnable{
private String TAG = "TcpClient";
private String  serverIP = "192.168.88.141";
private int serverPort = 1234;
private PrintWriter pw;
private InputStream is;
private DataInputStream dis;
private boolean isRun = true;
private Socket socket = null;
byte buff[]  = new byte[4096];
private String rcvMsg;
private int rcvLen;

public TcpClient(String ip , int port){
this.serverIP = ip;
this.serverPort = port;
}

public void closeSelf(){
isRun = false;
}

public void send(String msg){
pw.println(msg);
pw.flush();
}

@Override
public void run() {
try {
socket = new Socket(serverIP,serverPort);
socket.setSoTimeout(5000);
pw = new PrintWriter(socket.getOutputStream(),true);
is = socket.getInputStream();
dis = new DataInputStream(is);
} catch (IOException e) {
e.printStackTrace();
}
while (isRun){
try {
rcvLen = dis.read(buff);
rcvMsg = new String(buff,0,rcvLen,"utf-8");
Log.i(TAG, "run: 收到消息:"+ rcvMsg);
Intent intent =new Intent();
intent.setAction("tcpClientReceiver");
intent.putExtra("tcpClientReceiver",rcvMsg);
FuncTcpClient.context.sendBroadcast(intent);//将消息发送给主界面
if (rcvMsg.equals("QuitClient")){   //服务器要求客户端结束
isRun = false;
}
} catch (IOException e) {
e.printStackTrace();
}

}
try {
pw.close();
is.close();
dis.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}


以上,核心代码处理完成,通过以上,可以完成tcp 客户端对服务器的连接;

对应界面操作代码如下(几个类的介绍和UDP一样,不赘述):

package jason.tcpdemo.funcs;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.lang.ref.WeakReference;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Handler;

import jason.tcpdemo.R;
import jason.tcpdemo.coms.TcpClient;

/**
* Created by Jason Zhu on 2017-04-24.
*
*/

public class FuncTcpClient extends Activity {
private String TAG = "FuncTcpClient";
@SuppressLint("StaticFieldLeak")
public static Context context ;
private Button btnStartClient,btnCloseClient, btnCleanClientSend, btnCleanClientRcv,btnClientSend,btnClientRandom;
private TextView txtRcv,txtSend;
private EditText editClientSend,editClientID, editClientPort,editClientIp;
private static TcpClient tcpClient = null;
private MyBtnClicker myBtnClicker = new MyBtnClicker();
private final MyHandler myHandler = new MyHandler(this);
private MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
ExecutorService exec = Executors.newCachedThreadPool();

private class MyBtnClicker implements View.OnClickListener{

@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_tcpClientConn:
Log.i(TAG, "onClick: 开始");
btnStartClient.setEnabled(false);
btnCloseClient.setEnabled(true);
btnClientSend.setEnabled(true);
tcpClient = new TcpClient(editClientIp.getText().toString(),getPort(editClientPort.getText().toString()));
exec.execute(tcpClient);
break;
case R.id.btn_tcpClientClose:
tcpClient.closeSelf();
btnStartClient.setEnabled(true);
btnCloseClient.setEnabled(false);
btnClientSend.setEnabled(false);
break;
case R.id.btn_tcpCleanClientRecv:
txtRcv.setText("");
break;
case R.id.btn_tcpCleanClientSend:
txtSend.setText("");
break;
case R.id.btn_tcpClientRandomID:
break;
case R.id.btn_tcpClientSend:
Message message = Message.obtain();
message.what = 2;
message.obj = editClientSend.getText().toString();
myHandler.sendMessage(message);
exec.execute(new Runnable() {
@Override
public void run() {
tcpClient.send(editClientSend.getText().toString());
}
});
break;
}
}
}

private class MyHandler extends android.os.Handler{
private WeakReference<FuncTcpClient> mActivity;

MyHandler(FuncTcpClient activity){
mActivity = new WeakReference<FuncTcpClient>(activity);
}

@Override
public void handleMessage(Message msg) {
if (mActivity != null){
switch (msg.what){
case 1:
txtRcv.append(msg.obj.toString());
break;
case 2:
txtSend.append(msg.obj.toString());
break;
}
}
}
}

private class MyBroadcastReceiver extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {
String mAction = intent.getAction();
switch (mAction){
case "tcpClientReceiver":
String msg = intent.getStringExtra("tcpClientReceiver");
Message message = Message.obtain();
message.what = 1;
message.obj = msg;
myHandler.sendMessage(message);
break;
}
}
}

private int getPort(String msg){
if (msg.equals("")){
msg = "1234";
}
return Integer.parseInt(msg);
}

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tcp_client);
context = this;
bindID();
bindListener();
bindReceiver();
Ini();
}

private void bindID(){
btnStartClient = (Button) findViewById(R.id.btn_tcpClientConn);
btnCloseClient = (Button) findViewById(R.id.btn_tcpClientClose);
btnCleanClientRcv = (Button) findViewById(R.id.btn_tcpCleanClientRecv);
btnCleanClientSend = (Button) findViewById(R.id.btn_tcpCleanClientSend);
btnClientRandom = (Button) findViewById(R.id.btn_tcpClientRandomID);
btnClientSend = (Button) findViewById(R.id.btn_tcpClientSend);
editClientPort = (EditText) findViewById(R.id.edit_tcpClientPort);
editClientIp = (EditText) findViewById(R.id.edit_tcpClientIp);
editClientSend = (EditText) findViewById(R.id.edit_tcpClientSend);
txtRcv = (TextView) findViewById(R.id.txt_ClientRcv);
txtSend = (TextView) findViewById(R.id.txt_ClientSend);
}
private void bindListener(){
btnStartClient.setOnClickListener(myBtnClicker);
btnCloseClient.setOnClickListener(myBtnClicker);
btnCleanClientRcv.setOnClickListener(myBtnClicker);
btnCleanClientSend.setOnClickListener(myBtnClicker);
btnClientRandom.setOnClickListener(myBtnClicker);
btnClientSend.setOnClickListener(myBtnClicker);
}
private void bindReceiver(){
IntentFilter intentFilter = new IntentFilter("tcpClientReceiver");
registerReceiver(myBroadcastReceiver,intentFilter);
}
private void Ini(){
btnCloseClient.setEnabled(false);
btnClientSend.setEnabled(false);

}
}


记得添加权限:

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


效果图如下:



开发环境:Android Studio

附上demo包:

TCP(客户端和服务器demo)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: