本地开发+测试
Server端程序可以在eclipse或者DOS下运行,Client端程序与之相同。这样方便调试。
Client codes
Client.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class Client extends Thread {
private static Socket socket;
private static BufferedReader is;
private static PrintWriter os;
public void run() {
try {
os = new PrintWriter(socket.getOutputStream());
os.println(defaultSend());
os.flush();
BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String str = sin.readLine();
String meassge = "username:qz" + "longitude:117.130345" + "latitude:36.668129" + "bounds:2km"
+ "tags:学习" + "message:" + str;
os.println(meassge);
os.flush();
if (str.equals("end")) {
break;
}
}
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private String defaultSend(){
String meassge = "$username:qz" + "longitude:117.130345" + "latitude:36.668129" + "bounds:2km"
+ "tags:学习" + "message:";
return meassge;
}
public static void main(String[] args) throws Exception {
socket = new Socket(InetAddress.getLocalHost(), 5469);
Client client = new Client();
client.start();
is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
try {
String Msg = is.readLine();
if (Msg != null) {
int[] index = new int[8];
int defaultIndex = Msg.indexOf("ipAddress:");
if(defaultIndex == 1){
index[0] = Msg.indexOf("username:");
index[1] = Msg.indexOf("longitude:");
String username = Msg.substring(index[0]+"username:".length(), index[1]);
if(username.equals("1")){
index[2] = Msg.indexOf("counts:");
index[3] = Msg.indexOf("message:");
String counts = Msg.substring(index[2]+"counts:".length(), index[3]);
System.out.println("neighbor = "+counts);
}
}else{
index[0] = Msg.indexOf("ipAddress:");
index[1] = Msg.indexOf("username:");
index[2] = Msg.indexOf("longitude:");
index[3] = Msg.indexOf("latitude:");
index[4] = Msg.indexOf("bounds:");
index[5] = Msg.indexOf("tags:");
index[6] = Msg.indexOf("counts:");
index[7] = Msg.indexOf("message:");
String ipAddress = Msg.substring(index[0], index[1]);
String username = Msg.substring(index[1], index[2]);
String longitude = Msg.substring(index[2], index[3]);
String latitude = Msg.substring(index[3], index[4]);
String bounds = Msg.substring(index[4], index[5]);
String tags = Msg.substring(index[5], index[6]);
String counts = Msg.substring(index[6], index[7]);
String message = Msg.substring(index[7]);
String[] str = { ipAddress, username, longitude, latitude, bounds, tags, counts, message };
System.out.println("Server : " + Msg);
for (int i = 0; i < str.length; i++) {
System.out.println(str[i] + "\t");
}
}
}
} catch (Exception e) {
e.printStackTrace();
break;
}
}
// os.close();
// is.close();
System.out.println("end");
socket.close();
}
}
Server codes
ClientCopy.java
import java.io.PrintWriter;
import java.net.Socket;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ClientCopy extends Socket{
private Socket socket = null;
private String ipAddress;
private String longitude;
private String latitude;
private double bounds;
private String tags;
private PrintWriter printWriter;
public ClientCopy(Socket socket){
this.setSocket(socket);
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public double getBounds() {
return bounds;
}
public void setBounds(Double bounds) {
this.bounds = bounds;
}
public void setBounds(String bounds) {
this.bounds = getFormatBounds(bounds);
}
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
private static double getFormatBounds(String bounds){//得到km为单位的bounds
String unit;
double value = 0.1; //初始化为0.1km
Pattern pa1 = Pattern.compile("[0-9]+");
Pattern pa2 = Pattern.compile("[a-z]+");
Matcher ma1 = pa1.matcher(bounds);
Matcher ma2 = pa2.matcher(bounds);
if(ma1.find()){
value = Double.valueOf(ma1.group());
}
if(ma2.find()){
unit = ma2.group();
if(unit.equals("m")){
value = value / 1000;
}
}
return value;
}
public PrintWriter getPrintWriter() {
return printWriter;
}
public void setPrintWriter(PrintWriter printWriter) {
this.printWriter = printWriter;
}
}
MyServer.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MyServer extends Thread {
private static final double EARTH_RADIUS = 6378.137;
private static Lock linklistlock = new ReentrantLock();
private static Lock messagelock = new ReentrantLock();
private static LinkedList<String> messages = new LinkedList<String>();
private static LinkedList<ClientCopy> linklist = new LinkedList<ClientCopy>();
private static void addClient(ClientCopy cc) {
linklistlock.lock();
linklist.add(cc);
linklistlock.unlock();
}
private synchronized void deleteClient(ClientCopy cc) {
try {
if(cc.getPrintWriter() != null){
cc.getPrintWriter().close();
}
cc.getSocket().close();
linklistlock.lock();
System.out.println("clientCounts"+linklist.size());
linklist.remove(cc);
linklistlock.unlock();
} catch (IOException e) {
e.printStackTrace();
}
}
private synchronized void addMessage(String m) {// 将待发送的消息加入messages最后
messagelock.lock();
messages.addLast(m);
messagelock.unlock();
}
private synchronized void deleteMessages() {// 删除messages中最后一个元素
messagelock.lock();
messages.removeLast();
messagelock.unlock();
}
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(5469);// 创建一个ServerSocket在端口5469监听客户请求
MyServer ms = new MyServer();
Send send = ms.new Send();
send.start();
while (true) {
Socket ck = server.accept();// 使用accept()阻塞等待客户请求
ClientCopy ccy = new ClientCopy(ck);
Accepet ac = ms.new Accepet(ccy);
// linklistlock.lock();
// addClient(ccy);
// linklistlock.unlock();
ac.start();
}
}
class Accepet extends Thread {
private ClientCopy clientcopy;
private boolean tag = true;
private LinkedList<Socket> neighbor;
public Accepet(ClientCopy ccy) {
clientcopy = ccy;
neighbor = new LinkedList<Socket>();
}
public void run() {
try {
Socket client = clientcopy.getSocket();
BufferedReader is = new BufferedReader(new InputStreamReader(client.getInputStream()));
while (tag) {
String messa = is.readLine();
// if(messa==null)
// break;
if (messa == null)
throw new NullPointerException();
System.out.println(messa);
int defaultIndex = messa.indexOf("username:");
if (defaultIndex == 1) { // 根据消息头部判断是否为用户连接后自动发送的默认信息
linklistlock.lock();
getMesaages(clientcopy, messa);
addClient(clientcopy);
linklistlock.unlock();
String ipAddress = client.getInetAddress().toString().substring(1);
clientcopy.setIpAddress(ipAddress);
messa = messa.substring(defaultIndex);
final String str = "$ipAddress:" + ipAddress + messa;
System.out.println(str);
messagelock.lock();
addMessage(str);
messagelock.unlock();
} else {
int messageIndex = messa.indexOf("message:");
final String message = messa.substring(messageIndex + "message:".length());
if (!message.equals("end")) {
getMesaages(clientcopy, messa);
String ipAddress = client.getInetAddress().toString().substring(1);
clientcopy.setIpAddress(ipAddress);
final String str = "ipAddress:" + ipAddress + messa;
System.out.println(str);
messagelock.lock();
addMessage(str);
messagelock.unlock();
} else {// 结束
tag = false;
is.close();// 关闭Socket输入流
linklistlock.lock();
deleteClient(clientcopy);
linklistlock.unlock();
break;
}
}
}
} catch (Exception e) {
linklistlock.lock();
deleteClient(clientcopy);
linklistlock.unlock();
e.printStackTrace();
}
}
}
private void getMesaages(ClientCopy clientcopy, String messa) {
int[] index = new int[5];
index[0] = messa.indexOf("longitude:");
index[1] = messa.indexOf("latitude:");
index[2] = messa.indexOf("bounds:");
index[3] = messa.indexOf("tags:");
index[4] = messa.indexOf("message:");
String longitude = messa.substring((index[0] + "longitude:".length()), index[1]);
if(longitude.equals("null") || longitude == null){
longitude = "117.130345";
}
clientcopy.setLongitude(longitude);
String latitude = messa.substring((index[1] + "latitude:".length()), index[2]);
if(latitude.equals("null") || latitude == null){
latitude = "36.668129";
}
clientcopy.setLatitude(latitude);
String bounds = messa.substring((index[2] + "bounds:".length()), index[3]);
clientcopy.setBounds(bounds);
String tags = messa.substring((index[3] + "tags:".length()), index[4]);
clientcopy.setTags(tags);
}
class Send extends Thread {
public Send() {
}
public void run() {
while (true) {
// 取信息之前加锁
messagelock.lock();
int messagesSize = messages.size();
if (messagesSize <= 0) {
messagelock.unlock();
Thread.yield();
} else {
System.out.println("messagesSize:" + messagesSize);
try {
ClientCopy ccy = null;
PrintWriter os = null;
String Msg = null;
for (int j = messagesSize - 1; j >= 0; j--) {
Msg = messages.get(j);
linklistlock.lock();
int linklistSize = linklist.size();
LinkedList<ClientCopy> ll = new LinkedList<ClientCopy>();
int counts = 0 ;
for (int i = 0; i < linklistSize; i++) {
ccy = linklist.get(i);
if (getNeighbor(Msg, ccy)) {
ll.add(ccy);
counts++;
}
}
Msg = ensureNeighborCounts(Msg, counts);
System.out.println("counts = "+counts);
for(int i=0; i<ll.size();i++){
ccy = ll.get(i);
if (ccy.getPrintWriter() == null) {
ccy.setPrintWriter(new PrintWriter(ccy.getSocket().getOutputStream()));
}
os = ccy.getPrintWriter();
os.println(Msg);
os.flush();// 刷新输出流,使Client马上收到该字符串
}
ll = null ;
linklistlock.unlock();
deleteMessages();
}
} catch (IOException e) {
e.printStackTrace();
}
messagelock.unlock();
}
}
}
}
private String ensureNeighborCounts(String Msg, int counts){
//将待发送的消息添加neighbor字段
int index = Msg.indexOf("message:");
Msg = Msg.substring(0, index)+"counts:"+counts+Msg.substring(index);
return Msg;
}
private boolean getNeighbor(String message, ClientCopy ccy) {
boolean isNeighbor = false;
// 得到信息源的GPS定位信息、和消息发送范围
int[] index = new int[5];
index[0] = message.indexOf("longitude:");
index[1] = message.indexOf("latitude:");
index[2] = message.indexOf("bounds:");
index[3] = message.indexOf("tags:");
index[4] = message.indexOf("message:");
String tags0 = message.substring((index[3] + "tags:".length()), index[4]);
String tags1 = ccy.getTags();
if(tags0.equals(tags1)){
double longitude0 = Double.valueOf(message.substring((index[0] + "longitude:".length()), index[1]));
double latitude0 = Double.valueOf(message.substring((index[1] + "latitude:".length()), index[2]));
String bounds = message.substring((index[2] + "bounds:".length()), index[3]);
double bounds0 = getFormatBounds(bounds);
// 判断ccy是否为他的邻居
double longitude1 = Double.valueOf(ccy.getLongitude());
double latitude1 = Double.valueOf(ccy.getLatitude());
double bounds1 = ccy.getBounds();
System.out.println(longitude1 + " " + latitude1 + " " + bounds1);
double distance = GetDistance(longitude0, latitude0, longitude1, latitude1);
System.out.println("distance: " + distance);
if (distance <= bounds0 && distance <= bounds1) {
isNeighbor = true;
}
}
return isNeighbor;
}
private static double getFormatBounds(String bounds) {// 得到km为单位的bounds
String unit;
double value = 0.1; // 初始化为0.1km
Pattern pa1 = Pattern.compile("[0-9]+");
Pattern pa2 = Pattern.compile("[a-z]+");
Matcher ma1 = pa1.matcher(bounds);
Matcher ma2 = pa2.matcher(bounds);
if (ma1.find()) {
value = Double.valueOf(ma1.group());
}
if (ma2.find()) {
unit = ma2.group();
if (unit.equals("m")) {
value = value / 1000;
}
}
return value;
}
private static double rad(double d) {
return d * Math.PI / 180.0;
}
private static double GetDistance(double long1, double lat1, double long2, double lat2) {
// 根据两点间的经纬度计算距离,单位:km
double a, b, d, sa2, sb2;
lat1 = rad(lat1);
lat2 = rad(lat2);
a = lat1 - lat2;
b = rad(long1 - long2);
sa2 = Math.sin(a / 2.0);
sb2 = Math.sin(b / 2.0);
d = 2 * EARTH_RADIUS * Math.asin(Math.sqrt(sa2 * sa2 + Math.cos(lat1) * Math.cos(lat2) * sb2 * sb2));
return d;
}
}