如果客户端客户端之间需要发送定向信息,首先客户端发送内容消息之前需要发送认证信息,服务端接收到的数据以后首先判断是不是认证消息,比如默认以“#”开头的消息是认证消息。通过map的方式来存储认证信息和客户端

java端代码TCPServer.java
package com.ldw.socket.server;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class TCPServer {
//创建一个容器,存储客户端
//private static List<Socket> clients = new LinkedList<Socket>();
//认证信息和客户端信息
private static Map<String, Socket> clients = new LinkedHashMap<String, Socket>();
public static void main(String[] args) {
int port = 10002;
try {
ServerSocket server = new ServerSocket(port);
while (true) {
// 获得客户端连接
// 阻塞式方法
System.out.println("准备阻塞...");
final Socket client = server.accept();
System.out.println("阻塞完成...");
// 将客户端添加到容器中
//clients.add(client);
//开一个子线程防止阻塞,下面的内容是阻塞式的
new Thread(new Runnable() {
@Override
public void run() {
try {
// 输入流,为了获取客户端发送的数据
InputStream is = client.getInputStream();
// 输出流,给客户端写数据
OutputStream os = client.getOutputStream();
byte[] buffer = new byte[1024];
int len = -1;
System.out.println("准备read...");
while ((len = is.read(buffer)) != -1) {
System.out.println("read完成...");
String text = new String(buffer, 0, len);
System.out.println(text);
if (text.startsWith("#")) {
// 将客户端添加到 容器中
clients.put(text, client);
// 输出数据到客户端
os.write("认证成功".getBytes());
} else {
// 输出数据到客户端
os.write("收到你的请求".getBytes());
//拆分用户名和内容信息
String[] split = text.split(":");
String key = "#" + split[0];
String content = split[1];
System.out.println(content);
// 给谁发消息
Socket s = clients.get(key);
if (s != null) {
System.out.println("is not null");
OutputStream output = s.getOutputStream();
output.write(content.getBytes());
} else {
System.out.println("is null");
}
}
// 输出数据到客户端
//os.write("收到你的请求".getBytes());
//群发:将消息转给其他用户
// for (Socket s : clients) {
// if (s != client) {
// OutputStream output = s.getOutputStream();
// output.write(text.getBytes());
// }
// }
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
客户端通过Android来实现,布局文件,布局文件有几个按键,来方便触发
<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"
tools:context=".MainActivity" >
<EditText
android:id="@+id/et"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="认证内容"
android:id="@+id/et_auth"
/>
<Button
android:text="连接"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="clickConnect"
/>
<Button
android:text="认证"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="clickAuth"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="clickMessage"
android:text="通讯" />
<Button
android:text="断开连接"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="clickDisConnect"
/>
</LinearLayout>
逻辑代码MainActivity.java
package org.ldw.socket.client;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import org.ldw.socket.client.request.AuthRequest;
import org.ldw.socket.client.request.Request;
import org.ldw.socket.client.request.TextRequest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText et;
private EditText et_auth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et = (EditText) findViewById(R.id.et);
et_auth = (EditText) findViewById(R.id.et_auth);
}
private String dstName = "192.168.1.100";
private int dstPort = 10001;
private Socket client;
public void clickConnect(View v) {
new Thread(new Runnable() {
@Override
public void run() {
try {
// 三次握手
if (client == null || client.isClosed()) {
client = new Socket(dstName, dstPort);
}
InputStream is = client.getInputStream();
byte[] buffer = new byte[1024];
int len = -1;
while ((len = is.read(buffer)) != -1) {
final String text = new String(buffer, 0, len);
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), text,
Toast.LENGTH_SHORT).show();
}
});
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
public void clickAuth(View v) {
final String auth = et_auth.getText().toString().trim();
if (TextUtils.isEmpty(auth)) {
return;
}
// 数据通讯
OutputStream os;
try {
os = client.getOutputStream();
os.write(auth.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
public void clickMessage(View v) {
//获取输入框的内容
final String content = et.getText().toString().trim();
if (TextUtils.isEmpty(content)) {
return;
}
// 数据通讯
OutputStream os;
try {
os = client.getOutputStream();
os.write(content.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
public void clickDisConnect(View v) {
// 断开连接
try {
if (client != null && !client.isClosed()) {
client.close();
client = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
本文介绍了一种基于TCP的客户端认证机制及定向消息传递方法。服务端使用HashMap存储客户端认证信息,客户端通过发送特定格式的认证消息进行身份验证。认证成功后,客户端可以发送定向消息给指定接收方。
3314

被折叠的 条评论
为什么被折叠?



