1,客户端的实现:
package demo.com.socketchatclient;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import butterknife.Bind;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "socket";
@Bind(R.id.svContent)
ScrollView svContent;
@Bind(R.id.etText)
EditText etText;
@Bind(R.id.ll)
LinearLayout ll;
@Bind(R.id.llContainer)
LinearLayout llContainer;
private Socket socket;
private BufferedWriter out;
private BufferedReader in;
private int statusBarHeight;
private int widthPixels;
private int heightPixels;
private String hostAddress;
private Handler handler = new Handler(Looper.getMainLooper());
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
getStatusBarHeightAndScreenSize();
new Thread(new Runnable() {
@Override
public void run() {
initialSocket();
}
}).start();
}
private void getStatusBarHeightAndScreenSize() {
widthPixels = getResources().getDisplayMetrics().widthPixels;
heightPixels = getResources().getDisplayMetrics().heightPixels;
Rect frame = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
statusBarHeight = frame.top;
}
/**
* 初始化socket
*/
private void initialSocket() {
try {
socket = new Socket(InetAddress.getLocalHost(), 13422);
out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
hostAddress = socket.getInetAddress().getHostAddress();
receiveMsg();
Log.e(TAG, "initialSocket Socket链接成功");
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "socket链接成功", Toast.LENGTH_SHORT).show();
}
});
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "initialSocket: IOException=" + e.getMessage());
}
}
/**
* 接收信息
*/
private void receiveMsg() {
if (in == null) {
return;
}
new Thread(new Runnable() {
@Override
public void run() {
try {
String temp = null;
while ((temp = in.readLine()) != null) {
final String str = temp;
handler.post(new Runnable() {
@Override
public void run() {
showMsgOnScreen(hostAddress + " 说 :" + str);
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 发信息
* @param view
*/
public void sendMsg(View view) {
String text = etText.getText().toString();
if (text.equals("")) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "不能发空消息", Toast.LENGTH_SHORT).show();
}
});
return;
}
sendText(text);
}
private void sendText(String text) {
if (out == null) {
return;
}
try {
out.write(text);
out.newLine();
out.flush();
String str = "我说:" + text;
showMsgOnScreen(str);
etText.setText("");
} catch (IOException e) {
e.printStackTrace();
}
}
private void showMsgOnScreen(String text) {
TextView tv = new TextView(this);
tv.setLayoutParams(new LinearLayout.LayoutParams(widthPixels, LinearLayout.LayoutParams.WRAP_CONTENT));
tv.setText(text);
llContainer.addView(tv);
handler.postDelayed(new Runnable() {
@Override
public void run() {
svContent.fullScroll(ScrollView.FOCUS_DOWN);
}
}, 500);
}
/**
* 关流
*/
@Override
protected void onDestroy() {
super.onDestroy();
try {
if (socket != null) {
socket.shutdownInput();
socket.shutdownOutput();
socket.close();
}
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
<ScrollView
android:id="@+id/svContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/ll">
<LinearLayout
android:id="@+id/llContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
<LinearLayout
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="2dp"
android:background="@color/gray"
android:orientation="horizontal">
<EditText
android:id="@+id/etText"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="8" />
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:onClick="sendMsg"
android:text="发送" />
</LinearLayout>
</RelativeLayout>
package demo.com.socketchatdemo;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import butterknife.Bind;
import butterknife.ButterKnife;
import demo.com.socketchatdemo.utils.ThreadUtil;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "socket";
@Bind(R.id.svContent)
ScrollView svContent;
@Bind(R.id.etText)
EditText etText;
@Bind(R.id.ll)
LinearLayout ll;
@Bind(R.id.llContainer)
LinearLayout llContainer;
private int statusBarHeight;
private int widthPixels;
private int heightPixels;
private ArrayList<Socket> list = new ArrayList<>();
private ServerSocket serverSocket;
private int count;
Handler handler = new Handler(Looper.getMainLooper());
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
getStatusBarHeightAndScreenSize();
initialServerSocket();
}
private void getStatusBarHeightAndScreenSize() {
widthPixels = getResources().getDisplayMetrics().widthPixels;
heightPixels = getResources().getDisplayMetrics().heightPixels;
Rect frame = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
statusBarHeight = frame.top;
}
private void initialServerSocket() {
ThreadUtil.executeThreadTask(new Runnable() {
@Override
public void run() {
try {
serverSocket = new ServerSocket(13422);
count = 0;
while (true) {
Socket socket = serverSocket.accept();
handleSingleSocketClient(socket, count);
count++;
}
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "initialServerSocket: IOException=" + e.getMessage());
}
}
});
}
private void handleSingleSocketClient(final Socket socket, int count) {
list.add(count, socket);
ThreadUtil.executeThreadTask(new Runnable() {
@Override
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String hostAddress = socket.getInetAddress().getHostAddress();
receiveMsg(socket, in, hostAddress);
Log.e(TAG, "SocketServer链接成功");
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "handleSingleSocketClient: IOException=" + e.getMessage());
}
}
});
}
private void receiveMsg(Socket socket, BufferedReader in, final String address) {
try {
String temp = null;
while ((temp = in.readLine()) != null) {
final String str = temp;
Log.e(TAG, "receiveMsg: str=" + str);
handler.post(new Runnable() {
@Override
public void run() {
showMsgOnScreen(address + " 说 :" + str);
}
});
for (Socket s : list) {
if (s.isInputShutdown()) {
list.remove(s);
continue;
}
// if (!(s == socket)) {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
sendMsg(out, str);
// }
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendMsg(BufferedWriter out, String text) {
try {
out.write(text);
out.newLine();
out.flush();
showMsgOnScreen("Server:" + text);
} catch (IOException e) {
e.printStackTrace();
}
}
private void showMsgOnScreen(final String text) {
runOnUiThread(new Runnable() {
@Override
public void run() {
TextView tv = new TextView(MainActivity.this);
tv.setLayoutParams(new LinearLayout.LayoutParams(widthPixels, LinearLayout.LayoutParams.WRAP_CONTENT));
tv.setText(text);
llContainer.addView(tv);
handler.postDelayed(new Runnable() {
@Override
public void run() {
svContent.fullScroll(ScrollView.FOCUS_DOWN);
}
}, 100);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
for (Socket socket : list) {
try {
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
tools:context="demo.com.socketchatdemo.MainActivity">
<ScrollView
android:id="@+id/svContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/ll">
<LinearLayout
android:id="@+id/llContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
<LinearLayout
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="2dp"
android:background="@color/gray"
android:orientation="horizontal">
<EditText
android:id="@+id/etText"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="8" />
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:text="发送" />
</LinearLayout>
</RelativeLayout>
服务端工具类:
package demo.com.socketchatdemo.utils;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by Alv_chi on 2016/11/20.
*/
public class ThreadUtil {
private static ExecutorService executorService;
public static void executeThreadTask(Runnable r) {
if (executorService == null) {
executorService = Executors.newFixedThreadPool(15);
}
executorService.submit(r);
}
}
源码下载:点击打开链接下载源码