*近写了一个关于局域网socket通信的demo,代码和ui都很low,但是功能实现了,所以贴出来记录一下

主要流程如下

服务端:启动服务–>显示ip–>等待接收–>显示消息–>收到回复

客户端:录入ip–>输入消息–>发送消息–>收到结果

如下图

选择服务端还是客户端

%title插图%num

 

显示服务端ip

%title插图%num

客户端输入ip发送消息

%title插图%num

服务端收到消息

%title插图%num

主要代码如下:
服务端逻辑

public class ServiceActivity extends AppCompatActivity {

private TextView tv_clear;
private TextView tv_showIP;
private TextView tv_ip;
private TextView tv_msg;
private ServerSocket mServerSocket;
private Socket mSocket;
private StringBuffer sb = new StringBuffer();

@SuppressLint(“HandlerLeak”)
public Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1){
Bundle data = msg.getData();
sb.append(data.getString(“msg”));
sb.append(“\n”);
tv_msg.setText(sb.toString());
}
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service);
initView();
setListener();

try {
mServerSocket = new ServerSocket(1989);
} catch (IOException e) {
e.printStackTrace();
}
//启动服务线程
SocketAcceptThread socketAcceptThread = new SocketAcceptThread();
socketAcceptThread.start();
}

private void initView() {
tv_clear = (TextView) findViewById(R.id.tv_clear);
tv_showIP = (TextView) findViewById(R.id.tv_showIP);
tv_ip = (TextView) findViewById(R.id.tv_ip);
tv_msg = (TextView) findViewById(R.id.tv_msg);
}

private void setListener() {

tv_clear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sb.setLength(0);
tv_msg.setText(“”);
}
});
tv_showIP.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tv_ip.setText(NetWorkUtil.getIPAddress(ServiceActivity.this));
}
});

}

class SocketAcceptThread extends Thread{
@Override
public void run() {
try {
//等待客户端的连接,Accept会阻塞,直到建立连接,
//所以需要放在子线程中运行。
mSocket = mServerSocket.accept();
} catch (IOException e) {
e.printStackTrace();
Log.e(“info”, “run: ==============”+”accept error” );
return;
}
Log.e(“info”, “accept success==================”);
//启动消息接收线程
startReader(mSocket);
}
}

/**
* 从参数的Socket里获取*新的消息
*/
private void startReader(final Socket socket) {

new Thread(){
@Override
public void run() {
DataInputStream reader;
try {
// 获取读取流
reader = new DataInputStream(socket.getInputStream());
while (true) {
System.out.println(“*等待客户端输入*”);
// 读取数据
String msg = reader.readUTF();
System.out.println(“获取到客户端的信息:=” + msg);

//告知客户端消息收到
DataOutputStream writer = new DataOutputStream(mSocket.getOutputStream());
writer.writeUTF(“收到:” + msg); // 写一个UTF-8的信息

//发消息更新UI
Message message = new Message();
message.what = 1;
Bundle bundle = new Bundle();
bundle.putString(“msg”, msg);
message.setData(bundle);
handler.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}

@Override
protected void onDestroy() {
if (mServerSocket != null){
try {
mServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
super.onDestroy();
}
}
服务端UI

<LinearLayout
xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:app=”http://schemas.android.com/apk/res-auto”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:orientation=”vertical”
android:background=”#ffffff”
tools:context=”com.xiaoxiao9575.socketapplication.ServiceActivity”>

<LinearLayout
android:layout_width=”match_parent”
android:layout_height=”wrap_content”>
<TextView
android:id=”@+id/tv_showIP”
android:layout_width=”0dp”
android:layout_height=”wrap_content”
android:layout_weight=”1″
android:text=”显示IP”
android:gravity=”center”
android:padding=”15dp”
android:background=”#dddddd”/>
<TextView
android:id=”@+id/tv_clear”
android:layout_width=”0dp”
android:layout_height=”wrap_content”
android:layout_weight=”1″
android:text=”清除屏幕”
android:gravity=”center”
android:padding=”15dp”
android:background=”#dddddd”
android:layout_marginLeft=”5dp”/>
</LinearLayout>

<TextView
android:id=”@+id/tv_ip”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_margin=”10dp”/>

<TextView
android:id=”@+id/tv_msg”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_marginTop=”40dp”
android:layout_margin=”10dp”/>
</LinearLayout>
客户端逻辑

public class ClientActivity extends AppCompatActivity {

private EditText et_ip;
private EditText et_msg;
private TextView tv_send;
private TextView tv_confirm;

private Socket mSocket;
private OutputStream mOutStream;
private InputStream mInStream;
private SocketConnectThread socketConnectThread;
private StringBuffer sb = new StringBuffer();

@SuppressLint(“HandlerLeak”)
public Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1){
Bundle data = msg.getData();
sb.append(data.getString(“msg”));
sb.append(“\n”);
tv_msg.setText(sb.toString());
}
}
};
private TextView tv_msg;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
socketConnectThread = new SocketConnectThread();
initView();
setListener();
}

private void initView() {
et_ip = (EditText) findViewById(R.id.et_ip);
et_msg = (EditText) findViewById(R.id.et_msg);
tv_send = (TextView) findViewById(R.id.tv_send);
tv_confirm = (TextView) findViewById(R.id.tv_confirm);
tv_msg = (TextView) findViewById(R.id.tv_msg);
}

private void setListener() {
tv_send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
send(et_msg.getText().toString());
}
});
tv_confirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
socketConnectThread.start();
}
});
}

class SocketConnectThread extends Thread{
public void run(){
Log.e(“info”, “run: ============线程启动” );
try {
//指定ip地址和端口号
mSocket = new Socket(et_ip.getText().toString(), 1989);
if(mSocket != null){
//获取输出流、输入流
mOutStream = mSocket.getOutputStream();
mInStream = mSocket.getInputStream();
}else {
Log.e(“info”, “run: =========scoket==null”);
}
} catch (Exception e) {
e.printStackTrace();
return;
}
Log.e(“info”,”connect success========================================”);
startReader(mSocket);
}

}

public void send(final String str) {
if (str.length() == 0){
return;
}
new Thread() {
@Override
public void run() {
try {
// socket.getInputStream()
DataOutputStream writer = new DataOutputStream(mSocket.getOutputStream());
writer.writeUTF(str); // 写一个UTF-8的信息
System.out.println(“发送消息”);
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}

/**
* 从参数的Socket里获取*新的消息
*/
private void startReader(final Socket socket) {

new Thread(){
@Override
public void run() {
DataInputStream reader;
try {
// 获取读取流
reader = new DataInputStream(socket.getInputStream());
while (true) {
System.out.println(“*等待客户端输入*”);
// 读取数据
String msg = reader.readUTF();
System.out.println(“获取到客户端的信息:=” + msg);
Message message = new Message();
message.what = 1;
Bundle bundle = new Bundle();
bundle.putString(“msg”, msg);
message.setData(bundle);
handler.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
}
客户端UI

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout
xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:app=”http://schemas.android.com/apk/res-auto”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:orientation=”vertical”
tools:context=”com.xiaoxiao9575.socketapplication.ClientActivity”>

<EditText
android:id=”@+id/et_ip”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:hint=”ip”
/>
<TextView
android:id=”@+id/tv_confirm”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:text=”confirm”
android:padding=”20dp”
android:gravity=”center”
android:background=”#dddddd”/>
<EditText
android:id=”@+id/et_msg”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:hint=”msg”/>
<TextView
android:id=”@+id/tv_send”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:text=”send”
android:padding=”20dp”
android:gravity=”center”
android:background=”#dddddd”/>
<TextView
android:id=”@+id/tv_msg”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
/>
</LinearLayout>
获取ip代码

public static String getIPAddress(Context context) {
NetworkInfo info = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
if (info != null && info.isConnected()) {
if (info.getType() == ConnectivityManager.TYPE_MOBILE) {//当前使用2G/3G/4G网络
try {
//Enumeration<NetworkInterface> en=NetworkInterface.getNetworkInterfaces();
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
return inetAddress.getHostAddress();
}
}
}
} catch (SocketException e) {
e.printStackTrace();
}

} else if (info.getType() == ConnectivityManager.TYPE_WIFI) {//当前使用无线网络
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ipAddress = intIP2StringIP(wifiInfo.getIpAddress());//得到IPV4地址
return ipAddress;
}
} else {
//当前无网络连接,请在设置中打开网络
}
return null;
}

/**
* 将得到的int类型的IP转换为String类型
*
* @param ip
* @return
*/
public static String intIP2StringIP(int ip) {
return (ip & 0xFF) + “.” +
((ip >> 8) & 0xFF) + “.” +
((ip >> 16) & 0xFF) + “.” +
(ip >> 24 & 0xFF);
}
权限

<!–允许应用程序改变网络状态–>
<uses-permission android:name=”android.permission.CHANGE_NETWORK_STATE”/>
<!–允许应用程序改变WIFI连接状态–>
<uses-permission android:name=”android.permission.CHANGE_WIFI_STATE”/>
<!–允许应用程序访问有关的网络信息–>
<uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE”/>
<!–允许应用程序访问WIFI网卡的网络信息–>
<uses-permission android:name=”android.permission.ACCESS_WIFI_STATE”/>
<!–允许应用程序完全使用网络–>
<uses-permission android:name=”android.permission.INTERNET”/>