我开发了基于WiFi的套接字通信的示例Android应用,具有多个客户端。我使用 JsonWriter 来编写消息,使用 JsonReader 来读取消息。
当一对一的沟通没有问题,但一对多有一些问题。
例如:
我的服务器S1与客户端C1,C2和C3连接,当服务器尝试同时向所有客户端发送消息时,客户端C3仅接收消息而不接收其他消息。
ServerSocketClass
public class ServiceMain extends Service implements OnResponseJsonWriter {
private boolean isRunning = false;
private MyThread myThread;
static final int SocketServerPORT = 8080;
ServerSocket serverSocket;
static List<ChatClient> userList;
static String msgLog = "";
private String TAG = ServiceMain.class.getSimpleName();
private boolean isServerAction = false;
private String TOKEN_REQUEST;
private Context mContext;
private JsonWriter writer = null;
private JSON_Writer jsonWriter;
private DataInputStream dataInputStream = null;
private DataOutputStream dataOutputStream = null;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
mContext = ServiceMain.this;
userList = new ArrayList<ChatClient>();
myThread = new MyThread();
}
@SuppressWarnings("deprecation")
@Override
public synchronized void onDestroy() {
try {
if (isRunning) {
myThread.interrupt();
myThread.stop();
}
} catch (UnsupportedOperationException e) {
}
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!isRunning) {
myThread.start();
isRunning = true;
}
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onJsonWriterRespnse(boolean isSuccess) {
try {
writer.flush();
dataOutputStream.flush();
} catch (Exception e) {
Log.e(TAG, "onJsonWriterRespnse " + e);
}
}
class MyThread extends Thread {
static final long DELAY = 3000;
@Override
public void run() {
while (isRunning) {
try {
ChatServerThread chatServerThread = new ChatServerThread();
chatServerThread.start();
Thread.sleep(DELAY);
} catch (InterruptedException e) {
isRunning = false;
}
}
}
}
private class ChatServerThread extends Thread {
@Override
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SocketServerPORT);
while (true) {
socket = serverSocket.accept();
ChatClient client = new ChatClient();
userList.add(client);
ConnectThread connectThread = new ConnectThread(client, socket);
connectThread.start();
}
} catch (IOException e) {
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
class ChatClient {
String id;
Socket socket;
ConnectThread chatThread;
@Override
public String toString() {
return socket.getInetAddress().getHostAddress();
}
}
private class ConnectThread extends Thread {
Socket socket;
ChatClient connectClient;
String msgToSend = "";
ConnectThread(ChatClient client, Socket socket) {
connectClient = client;
this.socket = socket;
client.socket = socket;
client.chatThread = this;
}
@Override
public void run() {
try {
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream = new DataOutputStream(socket.getOutputStream());
String n = dataInputStream.readUTF();
connectClient.id = n;
socketConnectionResponse(connectClient, connectClient.id);
while (true) {
if (dataInputStream.available() > 0) {
}
isServerAction = false;
if (!msgToSend.equals("")) {
TeacherAttention attentionModel;
switch (msgToSend) {
case Constants.LOOK_AT_ME:
isServerAction = true;
TOKEN_REQUEST = Constants.LOOK_AT_ME;
msgToSend = "";
attentionModel = new TeacherAttention(Constants.TEACHER_ATTENTION_REQUEST,
Constants.RESPONSE_SUCCESS, Constants.LOOK_AT_ME);
writer = new JsonWriter(new OutputStreamWriter(dataOutputStream, "UTF-8"));
writer.setIndent(" ");
// for write JSON
jsonWriter = new JSON_Writer(mContext, writer, attentionModel, "");
break;
}
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Log.e("TAG", "finally??");
userList.remove(connectClient);
}
}
private void sendMsg(String msg) {
msgToSend = msg;
}
}
public static void broadcastMsgToAll(String msg) {
for (int i = 0; i < userList.size(); i++) {
userList.get(i).chatThread.sendMsg(msg);
}
}
/**
* send response to single user
*
* @param client
* @param userid
*/
public void socketConnectionResponse(ChatClient client, String userid) {
if (client != null) {
client.chatThread.sendMsg(userid);
} else {
Toast.makeText(ServiceMain.this, "No user connected", Toast.LENGTH_LONG).show();
}
}
}
ClientSocketClass:
public class ClientSocketService extends Service implements OnResponseJsonWriter,
OnResponseJsonReader {
private static String TAG = ClientSocketService.class.getSimpleName();
static final int socketServerPORT = 8080;
private ChatClientThread chatClientThread = null;
static String msgToSend = "";
static boolean goOut = false, isSocketRunning = false;
private JsonReader reader;
private Context mContext;
private DataOutputStream dataOutputStream = null;
private DataInputStream dataInputStream = null;
private JsonWriter writer = null;
private JSON_Reader jsonReader;
private JSON_Writer jsonWriter;
public static Socket socket = null;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
db = new DatabaseHelper(this);
getAllStudent = new ArrayList<>();
mContext = ClientSocketService.this;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
chatClientThread = new ChatClientThread(getUserID(), getTeacherIP(), socketServerPORT);
chatClientThread.start();
return super.onStartCommand(intent, flags, startId);
}
private class ChatClientThread extends Thread {
String name;
String dstAddress;
int dstPort;
ChatClientThread(String name, String address, int port) {
this.name = name;
dstAddress = address;
dstPort = port;
}
@Override
public void run() {
try {
socket = new Socket(dstAddress, dstPort);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF(name);
dataOutputStream.flush();
while (!goOut) {
if (dataInputStream.available() > 0) {
reader = new JsonReader(new InputStreamReader(dataInputStream, "UTF-8"));
try {
jsonReader = new JSON_Reader(mContext, reader);
} catch (Exception e) {
Log.e(TAG, "dataInputStream" + e);
} finally {
}
}
}
isSocketRunning = true;
}
} catch (UnknownHostException e) {
final String eString = e.toString();
Log.e("eString 1", "eString " + eString);
isSocketRunning = false;
} catch (IOException e) {
e.printStackTrace();
final String eString = e.toString();
Log.e("eString 2", "eString " + eString);
isSocketRunning = false;
} finally {
if (socket != null) {
try {
isSocketRunning = false;
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public static void sendMsg(String msg) {
msgToSend = msg;
}
private void disconnect() {
goOut = true;
}
public static boolean isSocketRunning() {
return isSocketRunning;
}
@Override
public void onJsonWriterRespnse(boolean isSuccess) {
try {
writer.flush();
dataOutputStream.flush();
} catch (IOException e) {
Log.e(TAG, "onJsonWriterRespnse " + e);
isSocketRunning = false;
}
}
@Override
public void onSocketReaderResponse(String requestToken, final ArrayList<SocketResponseModel> socketResponse) {
}
@Override
public void onSocketResponseUpdateIP(SocketResponseUpdateIp responsIp) {
}
@Override
public void onTeacherAttention(TeacherAttention teacherAttention) {
Intent lookIntent;
switch (teacherAttention.getTokenStatus()) {
case Constants.LOOK_AT_ME:
lookIntent = new Intent(this, LookAtMeActivity.class);
lookIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(lookIntent);
break;
}
}