本文介绍: 在前一个教程的基础上做了改进,还不错1、创建项目2、布局文件(1)<?xml version=”1.0″ encoding=”utf-8″?><LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android” xmlns:tools=”http://schemas.android.com/tools” android:layout_width=”match_pa..
1、创建项目
(1)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
>
<EditText
android:id="@+id/ed_client_ip"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:hint="IP"
android:text="127.0.0.1"
android:textSize="14sp"
/>
<EditText
android:id="@+id/ed_client_port"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="端口"
android:text="8801"
android:textSize="14sp"
/>
<Button
android:id="@+id/btn_start_client"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_margin="0dp"
android:padding="0dp"
android:text="连接服务"
android:textSize="14sp"
android:onClick="connectServer"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
>
<EditText
android:id="@+id/ed_client_send_message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="发送的消息"
android:text="from client"
android:textSize="14sp"
/>
<Button
android:id="@+id/btn_client_send"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_margin="0dp"
android:padding="0dp"
android:text="发送消息"
android:textSize="14sp"
android:onClick="SendMsgToServer"
/>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="客户端日志:"
android:textSize="14sp"
/>
<Button
android:id="@+id/btn_client_clear_message"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_margin="0dp"
android:padding="0dp"
android:text="清除日志"
android:textSize="14sp"
android:onClick="clearLog"
/>
</RelativeLayout>
<ListView
android:id="@+id/lv_client_msg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
(2)
<?xml version="1.0" encoding="utf-8"?>
<TextView
android:id="@+id/item_log"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Item Log goes here"
android:textSize="12sp"
/>
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>
3、主程序,注意分成2个了
(1)
package com.example.chentcpclientsenior;
import androidx.appcompat.app.AppCompatActivity;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Looper;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
TcpClient tcpClient=new TcpClient();
OnTcpClientConnectListener onTcpClientConnectListener = new OnTcpClientConnectListener();
private static final String TAG = "chenTcpSenior";
EditText mEdClientIp;
EditText mEdClientPort;
EditText mEdClientSendMessage;
ListView mLvClientMsg;
private String mClientIp;
private int mClientPort;
private Socket mClientSocket;
private BufferedReader mClientIn;
private PrintWriter mClientOut;
private String mClientSendMessage;
Button btn_start_client;
private List<String> mClientMessageList;
private ArrayAdapter<String> mClientMessageAdapter;
private boolean connectFlag = false; //是否已连接的标记,如果已连接就不新创建连接
// private Object OnTcpClientConnectListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//android.os.NetworkOnMainThreadException
//简单暴力,强制使用,代码修改简单(但是非常不推荐)
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
initView();
initData();
}
private void initView() {
mEdClientIp = findViewById(R.id.ed_client_ip);
mEdClientPort = findViewById(R.id.ed_client_port);
mEdClientSendMessage = findViewById(R.id.ed_client_send_message);
mLvClientMsg = findViewById(R.id.lv_client_msg);
btn_start_client = findViewById(R.id.btn_start_client);
}
private void initData() {
String serverIp = getLocalIpAddress();
Log.e(TAG, "initData serverIp=" + serverIp);
mEdClientIp.setText(serverIp);
mClientMessageList = new ArrayList<>();
mClientMessageAdapter = new ArrayAdapter<>(this, R.layout.item_log, R.id.item_log, mClientMessageList);
mLvClientMsg.setAdapter(mClientMessageAdapter);
}
//以太网消息处理的接口实现
public class OnTcpClientConnectListener implements TcpClient.OnConnectListener{
public void onConnectSuccess(String inetAddress, String localAddress)
{
Log.e(TAG, "onConnectSuccess");
logClient(getTime() +"onConnectSuccess");
setBtnConnectName(1); //1显示:断开连接;2显示:连接服务
connectFlag = true;
}
public void onConnectFail(Throwable e, String message){
Log.e(TAG, "onConnectFail");
logClient(getTime() +"onConnectFail "+message);
setBtnConnectName(2); //1显示:断开连接;2显示:连接服务
connectFlag = false;
}
public void onConnectError(Throwable e, String message)
{
Log.e(TAG, "onConnectError");
logClient(getTime() +"onConnectError "+message);
setBtnConnectName(2); //1显示:断开连接;2显示:连接服务
connectFlag = false;
}
public void onMessage(String message){
Log.e(TAG, "onMessage");
logClient(getTime() +"onMessage: " + message);
}
}
private void getClientPort() {
mClientPort = Integer.parseInt(mEdClientPort.getText().toString().trim());
}
private void getClientIp() {
mClientIp = mEdClientIp.getText().toString().trim();
}
private void getClientSendMessage() {
mClientSendMessage = mEdClientSendMessage.getText().toString().trim();
}
/**
* 获取WIFI下ip地址
*/
private String getLocalIpAddress() {
WifiManager wifiManager = (WifiManager) getApplicationContext().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 connectServer(View view) {
if( (connectFlag==false) && (btn_start_client.getText().equals("连接服务")) ){
getClientIp();
getClientPort();
tcpClient.connect(mClientIp,mClientPort, onTcpClientConnectListener);
}
else if( (connectFlag==true) &&(btn_start_client.getText().equals("断开连接")) ){
Log.e(TAG, "断开连接");
tcpClient.disconnect();
}
}
//发送信息到服务器
public void SendMsgToServer(View view) {
if (connectFlag==true) {
getClientSendMessage();
tcpClient.sendMessage(mClientSendMessage);
}
}
//清楚日志
public void clearLog(View view) {
mClientMessageList.clear();
mClientMessageAdapter.notifyDataSetChanged();
}
private void logClient(final String log) {
if (!isCurrentlyOnMainThread()) {
runOnUiThread(new Runnable() {
@Override
public void run() {
logClientReal(log);
}
});
} else {
logClientReal(log);
}
}
private void logClientReal(final String log) {
Log.d(TAG, log);
mClientMessageList.add(0, log);
mClientMessageAdapter.notifyDataSetChanged();
}
//连接服务器后设置btnConnect的名字提醒已连接获断开
private void setBtnConnectName(final int iType) {
if (!isCurrentlyOnMainThread()) {
runOnUiThread(new Runnable() {
@Override
public void run() {
setBtnConnectNameReal(iType);
}
});
} else {
setBtnConnectNameReal(iType);
}
}
private void setBtnConnectNameReal(final int iType) {
Log.d(TAG, String.valueOf(iType));
if(iType==1)
{
btn_start_client.setText("断开连接");
}
else if(iType==2){
btn_start_client.setText("连接服务");
}
}
/**
* 判断当前线程是否在主线程
*/
private boolean isCurrentlyOnMainThread() {
return Looper.myLooper() == Looper.getMainLooper();
}
/**
* 获取当前时间
*/
private String getTime() {
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss.SSS", Locale.CHINA);
return format.format(new Date());
}
}
(2)
package com.example.chentcpclientsenior;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
public class TcpClient {
private static final String TAG = "TcpClient";
private static TcpClient mTcpClient = new TcpClient();
private ClientSocketThread mClientSocketThread;
private OnConnectListener mOnConnectListener;
public static TcpClient getInstance() {
return mTcpClient;
}
public void setOnConnectListener(OnConnectListener onConnectListener) {
mOnConnectListener = onConnectListener;
}
public interface OnConnectListener {
/**
* @param inetAddress 服务端地址
* @param localAddress 客户端地址
*/
void onConnectSuccess(String inetAddress, String localAddress);
void onConnectFail(Throwable e, String message);
void onConnectError(Throwable e, String message);
void onMessage(String message);
}
public void setIp(String ip) {
mClientIp = ip;
}
public void setPort(int port) {
mClientPort = port;
}
public void connect() {
if (mOnConnectListener == null) {
throw new RuntimeException("请设置OnConnectListener");
}
if (mClientIp == null || mClientIp.length() == 0 || mClientPort == 0) {
mOnConnectListener.onConnectFail(new RuntimeException("请设置ip与port"), "请设置ip与port");
return;
}
if (mClientSocketThread == null) {
mClientSocketThread = new ClientSocketThread();
mClientSocketThread.start();
} else {
mOnConnectListener.onConnectError(new RuntimeException("已经建立连接"), "已经建立连接");
}
}
public void connect(String ip, int port, OnConnectListener onConnectListener) {
mOnConnectListener = onConnectListener;
mClientIp = ip;
mClientPort = port;
connect();
}
public void disconnect() {
if (mOnConnectListener == null) {
throw new RuntimeException("请设置OnConnectListener");
}
if (mClientSocket != null) {
try {
mClientSocket.close();
mClientIn.close();
mClientOut.close();
mClientOut = null;
mClientIn = null;
mClientSocket = null;
} catch (IOException e) {
e.printStackTrace();
}
} else {
mOnConnectListener.onConnectError(new RuntimeException("已经断开连接"), "已经断开连接");
}
mClientSocketThread.runnable.stopRun();
if (mClientSocketThread != null) {
mClientSocketThread = null;
}
}
public void sendMessage(String message) {
if (mOnConnectListener == null) {
throw new RuntimeException("请设置OnConnectListener");
}
mClientSendMessage = message;
clientSendMessage();
}
private void insideDisconnect() {
if (mClientSocket != null) {
try {
mClientSocket.close();
mClientIn.close();
mClientOut.close();
mClientOut = null;
mClientIn = null;
mClientSocket = null;
} catch (IOException e) {
e.printStackTrace();
}
}
if (mClientSocketThread != null) {
mClientSocketThread = null;
}
}
//=================================================================================
// Client
//=================================================================================
private String mClientIp;
private int mClientPort;
private Socket mClientSocket;
private BufferedReader mClientIn;
private PrintWriter mClientOut;
private String mClientSendMessage;
class ClientSocketThread extends Thread {
ClientReceiverRunnable runnable;
@Override
public void run() {
try {
mClientSocket = new Socket(mClientIp, mClientPort);
mClientIn = new BufferedReader(new InputStreamReader(mClientSocket.getInputStream()));
mClientOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mClientSocket.getOutputStream())), true);
//ClientReceiverRunnable runnable = new ClientReceiverRunnable(mClientSocket);
runnable = new ClientReceiverRunnable(mClientSocket);
new Thread(runnable).start();
if (mOnConnectListener != null) {
mOnConnectListener.onConnectSuccess(mClientSocket.getInetAddress().getHostAddress(), mClientSocket.getLocalAddress().getHostAddress());
}
} catch (IOException e) {
if (mOnConnectListener != null) {
mOnConnectListener.onConnectFail(e, "服务器没有开启");
}
insideDisconnect();
e.printStackTrace();
}
}
}
class ClientReceiverRunnable implements Runnable {
boolean isContinue = true;
char cb[]= new char[2000]; //暂时设定最大接收2000byte
int iReceiveCount=0;
private Socket socket;
public ClientReceiverRunnable(Socket socket) {
this.socket = socket;
}
public void stopRun()
{
isContinue = false;
}
@Override
public void run() {
// boolean isContinue = true;
while (isContinue) {
try {
if (socket != null && !socket.isClosed() && socket.isConnected() && !socket.isInputShutdown()) {
String clientReceiverMessage;
//if ((clientReceiverMessage = mClientIn.readLine()) != null) {//服务器断开连接时,读取的内容为null,这与发送消息为“”不同
iReceiveCount=mClientIn.read(cb);
if(iReceiveCount>0){
char showCb[] = new char[iReceiveCount];
//public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
System.arraycopy(cb, 0, showCb, 0, iReceiveCount);
clientReceiverMessage = String.valueOf(showCb);
// 客户端接收到消息
if (mOnConnectListener != null) {
mOnConnectListener.onMessage(clientReceiverMessage);
}
} else {
//服务端断开连接
isContinue = false;
if (mOnConnectListener != null) {
mOnConnectListener.onConnectError(new RuntimeException("服务器断开连接"), "服务器断开连接");
}
insideDisconnect();
}
}
} catch (Exception e) {
isContinue = false;
e.printStackTrace();
if (mOnConnectListener != null) {
mOnConnectListener.onConnectError(e, "客户端连接超时");
}
}
}
try {
if (socket != null) {
socket.close();
}
if (mClientIn != null) {
mClientIn.close();
}
if (mClientOut != null) {
mClientOut.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void clientSendMessage() {
if (mClientSendMessage == null || mClientSendMessage.length() == 0) {
if (mOnConnectListener != null) {
mOnConnectListener.onConnectError(new RuntimeException("请输入内容"), "请输入内容");
}
return;
}
if (mClientSocket != null && mClientSocket.isConnected() && !mClientSocket.isOutputShutdown()
&& mClientOut != null) {
mClientOut.println(mClientSendMessage);
} else {
if (mOnConnectListener != null) {
mOnConnectListener.onConnectError(new RuntimeException("客户端已经断开连接"), "客户端已经断开连接");
}
}
}
}
4、注意权限设置
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
原文地址:https://blog.csdn.net/chencaw/article/details/122981311
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_39434.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。