Покритикуйте код моего сокет сервера для игрового чата
| |
KVinS | Дата: Суббота, 19 Мая 2012, 17:36 | Сообщение # 1 |
постоянный участник
Сейчас нет на сайте
| С помощью пары уроков, сделал сервер для визуального чата, типа галактики знакомств. Интересны советы по упрощению и оптимизации. Там в принципе ничего сложного, но названия переменных и комментарии, оставшиеся с уроков, могут сбить с толка. Особенно интересно про многопоточность и работу с БД.
Главный сервер Code /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package Server;
import java.io.BufferedOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.ServerSocket; import java.net.Socket; import Server.Client.*; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.TreeMap; import Server.PolicyServer.*; import java.util.HashSet; import java.util.Properties; import java.util.Set;
/** * * @author Escalade */ public class GeneralServer extends Thread {
final public TreeMap<Integer, Client> userMap = new TreeMap<Integer, Client>(); final public TreeMap<String, Integer> userNickMap = new TreeMap<String, Integer>(); public ServerSocket serverSocket; final public TreeMap<Integer, Location> Locations = new TreeMap<Integer, Location>();
public int getId(String nik) { if (userNickMap.get(nik) != null) { return userNickMap.get(nik); } else { return 0; } }
public GeneralServer(int port) throws IOException { properties.setProperty("user", "WCRG3"); properties.setProperty("password", "wpdDKR7qpz3JjGTf"); properties.setProperty("useUnicode", "true"); properties.setProperty("characterEncoding", "UTF-8");
Locations.put(0, new Location(0, "Стартовая", 100, 100, 0, 0)); System.out.println(Locations.get(0).level1.toString()); serverSocket = new ServerSocket(port); System.out.println(" Сервер запущен: "); System.out.println(" IP: " + serverSocket.getInetAddress().getHostAddress()); System.out.println(" Port: " + serverSocket.getLocalPort()); // Запуск потока из конструктора (так не рекомендуеться, но удобно) start();
while (true) { BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); String str = input.readLine(); System.out.println(str); }
} public int users = 0; public Properties properties = new Properties();
@Override public void run() {
while (true) { try { // Метод accept() блочит данный поток пока не подключиться новый пользователь Socket socket = serverSocket.accept(); // Создание нового потока-обработчика для подключенного пользователя // он выполняется паралельно данному потоку, и ниче не блочит. // Сервер переходит к готовности принять новое соединение Client handler = new Client(this, socket); users++; } catch (Exception ex) { } } }
public static void log(String str) { System.out.println(str); } private int i;
public void massendMessage(String message, int to, String from) { // System.out.println("На отправку пришло" + message + " " +to +" "+from);
if (to == -1) { synchronized (userMap) { for (Client socketHandler : userMap.values()) { try {
BufferedOutputStream printer = socketHandler.getPrintStream();
printer.write(("ch" + from + ": " + message).getBytes("UTF-8"));
printer.flush();
i = i + 1; } catch (Exception ex) { } } } } }
public void PM(String from, int to, String message) throws UnsupportedEncodingException, IOException { synchronized (userMap) { BufferedOutputStream printer = userMap.get(to).getPrintStream(); printer.write(("chp" + from + ": " + message).getBytes("UTF-8")); printer.flush(); } }
public void MoveChar(int location, int id, int startX, int startY, int conecX, int conecY) { synchronized (Locations.get(location).usersId) { //Locations.get(location).usersId //System.out.println("move");
for (int socketHandlerId : Locations.get(location).usersId) { try { // System.out.println("id " + socketHandlerId); userMap.get(socketHandlerId).writePrintStream("mv" + id + "|" + startX + "|" + startY+ "|" + conecX + "|" + conecY);
// printer.write(().getBytes("UTF-8")); // printer.flush(); } catch (Exception ex) { } } } }
public void onlineChar(int location, int id, int addX, int addY, String vid) { synchronized (Locations.get(location).usersId) { //Locations.get(location).usersId
for (int socketHandlerId : Locations.get(location).usersId) { try { if (socketHandlerId!=id){ // BufferedOutputStream printer = userMap.get(socketHandlerId).getPrintStream(); // // printer.write(("on" + id + "|" + addX + "|" + addY+"|"+vid).getBytes("UTF-8")); // printer.flush();
userMap.get(socketHandlerId).writePrintStream("on" + id + "|" + addX + "|" + addY+"|"+vid); }
} catch (Exception ex) { } } } }
public void oflineChar(int location, int id) { synchronized (Locations.get(location).usersId) { //Locations.get(location).usersId
for (int socketHandlerId : Locations.get(location).usersId) { try {
// BufferedOutputStream printer = userMap.get(socketHandlerId).getPrintStream();
//printer.write(("of" + id).getBytes("UTF-8")); //printer.flush(); userMap.get(socketHandlerId).writePrintStream("of" + id); } catch (Exception ex) { } } } }
public static void main(String[] args) throws IOException { //System.out = new PrintWriter("matrend.txt");
// (new PolicyServer(843, new String[] {"*:500" })).start(); GeneralServer server = new GeneralServer(4444); } }
Игра про лесных котов
|
|
| |
Vinchensoo | Дата: Суббота, 19 Мая 2012, 17:39 | Сообщение # 2 |
Злобный социопат с комплексом Бога
Сейчас нет на сайте
| Хорошая статья по многопоточности
|
|
| |
KVinS | Дата: Суббота, 19 Мая 2012, 17:40 | Сообщение # 3 |
постоянный участник
Сейчас нет на сайте
| Класс клиентаCode /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package Server;
/** * * @author 1 */ import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.Socket; import Server.MySQL.*;
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.SQLException;
/** * * @author Escalade */ public class Client extends Thread {
// Хранит всех пользователей // private LinkedList<Client> servak.userList = null; // Сокет пользователя с которым работает данный поток private Socket socket = null; // Входной канал private BufferedInputStream bufferedReader = null; // Выходной канал private BufferedOutputStream printStream = null; // Имя пользователя private String userName; private int userX; private int userY; private int userAnimation; private int userHP; private int userHpMax; private int userLocation; public int userId; public int dostup = 0; public int userStr; public int userDex; public int userInt; public int userVin; public int userFree; public String userVid; // 0 - не авторизирован // 1 - авторизирован private GeneralServer BaseServer;
/** * Конструктор * @param users * @param socket * @throws IOException */ public Client(GeneralServer servak, Socket socket) throws IOException { super("Client Thread");
this.BaseServer = servak; this.socket = socket; userX = 0; userY = 0; userLocation = 0; bufferedReader = new BufferedInputStream(socket.getInputStream()); printStream = new BufferedOutputStream(socket.getOutputStream()); start(); }
/** * Возвращает имя пользователя * @return */ public String getUserName() { return userName; }
/** * Возвращает выходной поток * @return */ public BufferedOutputStream getPrintStream() { return printStream; }
public void writePrintStream(String s) throws IOException { byte[] mes_byte = s.getBytes("UTF-8");
Integer length = mes_byte.length; String length_string = length.toString(); byte[] length_byte = length_string.getBytes("UTF-8");
Integer length_length = length_byte.length; String length_length_string = length_length.toString(); byte[] length_length_byte = length_length_string.getBytes("UTF-8");
//byte[] length_length_byte = new byte [length.length];
printStream.write(length_length_byte); printStream.write(length_byte); printStream.write(s.getBytes("UTF-8")); // System.out.println(userId + " принял на запись " + s); // printStream.write(s.getBytes("UTF-8")); printStream.flush(); }
public int getHP() { return userHP; }
public int getX() { return userX; }
public int getY() { return userY; }
public void changeHP(int deltaLife) { userHP += deltaLife; if (userHP <= 0) { } } private long nowSec; private long moveSecOK;
public void changeXY(int deltaX, int deltaY) { nowSec = System.currentTimeMillis(); if (nowSec >= moveSecOK) {
BaseServer.MoveChar(userLocation, userId, userX, userY, (userX + deltaX), (userY + deltaY));
userX += deltaX; userY += deltaY;
moveSecOK = nowSec + 750; } } private String b1; private String b2; private int i; private int j;
private void parser(String zapros) throws SQLException, UnsupportedEncodingException, IOException {
b1 = zapros.substring(0, 2);
if (b1.equals("ch")) { b1 = zapros.substring(2, 3); if (b1.equals("@")) { //Приват if (dostup >= 0) { b1 = zapros.substring(3, zapros.length());
i = b1.indexOf(","); b2 = b1.substring(0, i); b1 = b1.substring(i, zapros.length()); i = BaseServer.getId(b2); if (i > 0) { BaseServer.PM(userName, i, b1); } else { // writePrintStream("Пользователь не в игре или не существует."); } } } else { //Просто чат if (dostup >= 0) { b1 = zapros.substring(2, zapros.length()); BaseServer.massendMessage(b1, -1, userName); } } } else if (b1.equals("mv")) { //System.out.println("Go est"); if (dostup > 0) { b1 = zapros.substring(2, zapros.indexOf("|"));
b2 = zapros.substring(zapros.indexOf("|") + 1, zapros.length());
// System.out.println(b1 + " " + b2);
changeXY(Integer.parseInt(b1), Integer.parseInt(b2)); } } else if (b1.equals("sy")) { b1 = zapros.substring(2, 4); if (b1.equals("au")) { //Авторизация if (dostup == 0) { b1 = zapros.substring(4, zapros.indexOf("|"));
b2 = zapros.substring(zapros.indexOf("|") + 1, zapros.length()); // System.out.println(b1+" "+ b2); b1 = Authorization(b1, b2); if (b1.equals("t")) { writePrintStream("syaut|" + userName + "|" + userX + "|" + userY + "|" + userLocation + "|" + userId + "|" + dostup + "|" + userStr + "|" + userDex + "|" + userInt + "|" + userVin + "|" + userFree); //writePrintStream(BaseServer.Locations.get(userLocation).level1.toString()); BaseServer.onlineChar(userLocation, userId, userX, userY, userVid);
//Рассылка кто из игроков онлайн synchronized (BaseServer.Locations.get(userLocation).usersId) { for (int socketHandlerId : BaseServer.Locations.get(userLocation).usersId) { try { // System.out.println(socketHandlerId + " " + userId); if (userId != socketHandlerId) { System.out.println("Отправил о"+ socketHandlerId + ", " + userId);
writePrintStream("on" + BaseServer.userMap.get(socketHandlerId).userId + "|" + BaseServer.userMap.get(socketHandlerId).userX + "|" + BaseServer.userMap.get(socketHandlerId).userY + "|" + BaseServer.userMap.get(socketHandlerId).userVid); } } catch (Exception ex) { } } } //Конец рассылки
} else if (b1.equals("f2")) { writePrintStream("syauf2"); } else { writePrintStream("syauf1"); } } } else if (b1.equals("rg")) { //Регистрация
if (dostup == 0) { b1 = zapros.substring(5, zapros.length()); b1 = Registration(b1);
writePrintStream("syrg" + b1);
// int j = 0; // for (j = 0; j < reg_massiv.length; j++) { // System.out.println(j + " " + reg_massiv[j]); // }
} } } }
Игра про лесных котов
|
|
| |
Vinchensoo | Дата: Суббота, 19 Мая 2012, 17:49 | Сообщение # 4 |
Злобный социопат с комплексом Бога
Сейчас нет на сайте
| Приглядись еще к этому, кстати
|
|
| |
KVinS | Дата: Суббота, 19 Мая 2012, 17:51 | Сообщение # 5 |
постоянный участник
Сейчас нет на сайте
| Продолжение кода Code private String Registration(String b1) throws SQLException { dostup = -1; String nik = "f"; String login = "f"; String email = "f";
String[] reg_massiv = b1.split(";");
String zapros;// = "SELECT * FROM users where login like '" + reg_massiv[0] + "' OR nickname like '" + reg_massiv[3] + "' OR email like '" + reg_massiv[2] + "' limit 1;"; //System.out.println(zapros); Connection con = null; PreparedStatement stmt = null; // Statement stmt = null; ResultSet result = null; String url = "jdbc:mysql://localhost:3306/wcrg3";
try { con = DriverManager.getConnection(url, BaseServer.properties); stmt = con.prepareStatement("SELECT * FROM users where login = ? OR nickname = ? OR email = ? limit 1;"); stmt.setString(1, reg_massiv[0]); stmt.setString(2, reg_massiv[3]); stmt.setString(3, reg_massiv[2]); // stmt = con.createStatement(); result = stmt.executeQuery();
if (result.next()) { nik = result.getString("nickname"); if (!nik.equals(reg_massiv[3])) { nik = "t"; } else { nik = "f"; } email = result.getString("email"); if (!email.equals(reg_massiv[2])) { email = "t"; } else { email = "f"; } login = result.getString("login"); if (!login.equals(reg_massiv[0])) { login = "t"; } else { login = "f"; }
} else { nik = "t"; login = "t"; email = "t";
}
} catch (Exception e) { } finally { // Эта часть закроет все открытые ресуры // В противном случае возмжожны проблемы. try { if (result != null) { result.close(); } if (stmt != null) { stmt.close(); } if (con != null) { con.close(); }
} catch (SQLException ex) { System.err.println("Error: " + ex.getMessage()); } zapros = login + nik + email; boolean validnost = true; int flag = 0; String str = reg_massiv[3]; char[] nikChars1 = {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'l', 'k', 'j', 'h', 'g', 'f', 'd', 's', 'a', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ' ', '-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}; char[] nikChars2 = {'й', 'ц', 'у', 'к', 'е', 'н', 'г', 'ш', 'щ', 'з', 'х', 'ъ', 'э', 'ж', 'д', 'л', 'о', 'р', 'п', 'а', 'в', 'ы', 'ф', 'я', 'ч', 'с', 'м', 'и', 'т', 'ь', 'б', 'ю', ' ', '-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}; char[] miloChars = {'=', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'l', 'k', 'j', 'h', 'g', 'f', 'd', 's', 'a', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '@', '.', '_', '-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}; char[] loginChars = {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'l', 'k', 'j', 'h', 'g', 'f', 'd', 's', 'a', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ' ', '-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}; char[] specChars = {'-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
str = reg_massiv[3].toLowerCase();
flag = 0; if (zapros.equals("ttt")) { for (i = 0; i < str.length(); i++) { for (j = 0; j < nikChars1.length; j++) { if (str.charAt(i) == nikChars1[j]) { flag++; } } } if (flag != str.length()) { flag = 0; for (i = 0; i < str.length(); i++) { for (j = 0; j < nikChars2.length; j++) { if (str.charAt(i) == nikChars2[j]) { flag++; } } } if (flag != str.length()) { validnost = false; } }
flag = 0; for (i = 0; i < str.length(); i++) {
if (str.charAt(i) == ' ') { flag++; }
} if (flag >= 4) { validnost = false; }
flag = 0; for (i = 0; i < str.length(); i++) {
for (j = 0; j < specChars.length; j++) { if (str.charAt(i) == specChars[j]) { flag++; } } } if (flag > (str.length() / 4)) { validnost = false; }
flag = 0; str = reg_massiv[0].toLowerCase(); for (i = 0; i < str.length(); i++) {
for (j = 0; j < loginChars.length; j++) { if (str.charAt(i) == loginChars[j]) { flag++; } } }
if (flag != str.length()) { validnost = false; } System.out.println("4" + validnost); flag = 0; str = reg_massiv[2].toLowerCase(); for (i = 0; i < str.length(); i++) {
for (j = 0; j < miloChars.length; j++) { if (str.charAt(i) == miloChars[j]) { flag++; } }
} if (flag != str.length()) { validnost = false; } System.out.println("5" + validnost);
if (validnost && (Integer.parseInt(reg_massiv[5]) + Integer.parseInt(reg_massiv[6]) + Integer.parseInt(reg_massiv[7]) + Integer.parseInt(reg_massiv[8]) + Integer.parseInt(reg_massiv[9])) == 10) { con = DriverManager.getConnection(url, BaseServer.properties); stmt = con.prepareStatement("INSERT INTO `users` (`id`, `login`, `password`, `nickname`, `email`, `userX`, `userY`, `userLocation`, `dostup`, `userStr`, `userDex`, `userInt`, `userVin`, `userFree`, `dateRegistration`, `dateAuthorization`, `userVid`) VALUES (NULL, ?, ?, ?, ?, 10, 10, 0, 1, ?, ?, ?, ?, ?, NOW(), CURRENT_TIMESTAMP, ?);");
stmt.setString(1, reg_massiv[0]); stmt.setString(2, reg_massiv[1]); stmt.setString(3, reg_massiv[3]); stmt.setString(4, reg_massiv[2]); stmt.setString(5, reg_massiv[5]); stmt.setString(6, reg_massiv[6]); stmt.setString(7, reg_massiv[7]); stmt.setString(8, reg_massiv[8]); stmt.setString(9, reg_massiv[9]); stmt.setString(10, reg_massiv[4]);
stmt.executeUpdate();
try { if (result != null) { result.close(); } if (stmt != null) { stmt.close(); } if (con != null) { con.close(); }
} catch (SQLException ex) { System.err.println("Error: " + ex.getMessage()); } } else { return ("hacker"); } } // System.out.println("-" + login + nik + email);
dostup = 0; return (login + nik + email);
}
}
private String Authorization(String b1, String b2) throws SQLException { dostup = -1; String auth = "f1";
Connection con = null; PreparedStatement stmt = null; // Statement stmt = null; ResultSet result = null; try {
String url = "jdbc:mysql://localhost:3306/wcrg3"; con = DriverManager.getConnection(url, BaseServer.properties); // stmt = con.createStatement(); stmt = con.prepareStatement("SELECT * FROM users where login = ? and password = ? limit 1;"); System.out.println("k=" + stmt + " " + b1 + " " + b2); stmt.setString(1, b1); stmt.setString(2, b2); System.out.println("k=" + stmt);
result = stmt.executeQuery(); if (result.next()) {
Client usaut; synchronized (BaseServer.userMap) { usaut = BaseServer.userMap.get(result.getInt("id"));
if (usaut == null) { userName = result.getString("nickname"); userX = result.getInt("userX"); userY = result.getInt("userY"); userLocation = result.getInt("userLocation"); userId = result.getInt("id"); dostup = result.getInt("dostup");
userStr = result.getInt("userStr"); userDex = result.getInt("userDex"); userInt = result.getInt("userInt"); userVin = result.getInt("userVin"); userFree = result.getInt("userFree");
userVid = result.getString("userVid"); System.out.println(userName + " авторизировался"); //synchronized (this) { synchronized (BaseServer.userMap) { BaseServer.userMap.put(userId, this); }
synchronized (BaseServer.userNickMap) { BaseServer.userNickMap.put(userName, userId); }
synchronized (BaseServer.Locations.get(userLocation).usersId) { BaseServer.Locations.get(userLocation).usersId.add(userId); } //} auth = "t"; } else { auth = "f2"; } } } else { auth = "f1"; dostup = 0; }
} catch (Exception e) { System.out.println(e); } finally { // Эта часть закроет все открытые ресуры // В противном случае возмжожны проблемы. try { if (result != null) { result.close(); } if (stmt != null) { stmt.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { System.err.println("Error: " + ex.getMessage()); }
} return (auth); } /** * Основной метод-обработчик потока */ private byte[] message; private byte[] messageLengthLength; private byte[] messageLength = new byte[1]; private int cc; private int messageLengthLengthInt; private String s; private String messageString;
@Override public void run() { try { //GeneralServer.log("jbfb"); System.out.println("Есть входящее соединение: " + socket.getInetAddress()); // Предлагаем пользователю ввести свое имя writePrintStream("syv1"); while ((cc = bufferedReader.read()) != -1) { try { messageLengthLength = new byte[1]; //Читаем длину длины s = null;
bufferedReader.read(messageLengthLength);
s = new String(messageLengthLength, "UTF-8"); //Переводим длину длины из байт
// System.out.println("длина длины " + s); messageLengthLengthInt = new Integer(s);
messageLength = null; messageLength = new byte[messageLengthLengthInt];
bufferedReader.read(messageLength);
s = null; s = new String(messageLength, "UTF-8");
System.out.println("длина " + s);
messageLengthLengthInt = new Integer(s); //Переводим длину из байт message = null; message = new byte[messageLengthLengthInt]; //создаем массив соответствующего размера
bufferedReader.read(message);//заполняем его System.out.println("сообщение:" + message); System.out.println("<" + userName + ">: " + new String(message, "UTF-8"));//результат
messageString = new String(message, "UTF-8");
// messageString = new String(messageLength, "UTF-8"); parser(messageString); messageString = null; message = null; s = null; messageLength = null; // System.gc(); } catch (Exception ex) { closeSocket(); break; } } closeSocket();
} catch (Exception ex) { closeSocket(); }
}
/** * Удаляет пользователя из списка онлайн пользователей и освобождает ресурсы сокета */ private void closeSocket() { try { System.out.println("Пользователь " + userName + " покинул игру");
BaseServer.oflineChar(userLocation, userId);
synchronized (BaseServer.Locations.get(userLocation).usersId) { BaseServer.Locations.get(userLocation).usersId.remove(userId); } synchronized (BaseServer.userMap) { BaseServer.userMap.remove(userId); } synchronized (BaseServer.userNickMap) { BaseServer.userNickMap.remove(userName); }
bufferedReader.close(); printStream.close(); socket.close(); // System.gc(); } catch (Exception ex) { } } }
Ну и комната Code package Server;
import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set;
public class Location {
final public HashSet<Integer> usersId = new HashSet<Integer>(); public List level1 = new ArrayList(); public int location_id, location_width, location_height, location_globalX, location_globalY; public String location_title;
public Location(int id, String title, int width, int height, int globalX, int globalY) { location_id = id; location_width = width; location_height = height; location_globalX = globalX; location_globalY = globalY; location_title = title; } }
Игра про лесных котов
|
|
| |
Vinchensoo | Дата: Суббота, 19 Мая 2012, 18:12 | Сообщение # 6 |
Злобный социопат с комплексом Бога
Сейчас нет на сайте
| KVinS, если хочешь, чтобы ктото почитал код- залей на нормальный хост кодов, с подсветкой синтаксиса, все дела =)
|
|
| |
BabS | Дата: Среда, 25 Июля 2012, 17:04 | Сообщение # 7 |
частый гость
Сейчас нет на сайте
| Все очень сумбурно )). Почему не сделать общение с базой по стандартам JavaBeans? Не пробовал сначала спроектировать нормально? Странно как-то реализована валидация, не проще сделать проверку на клиенте+регулярные выражения?
|
|
| |
KVinS | Дата: Воскресенье, 05 Августа 2012, 17:02 | Сообщение # 8 |
постоянный участник
Сейчас нет на сайте
| И что же это за стандарты?
Проверка на клиенте? Знаете такое выражение 'клиент у врага'?
Игра про лесных котов
|
|
| |
|