Skip to Main Content

Java APIs

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Find All Counter Strike Servers in a LAN

843790Jan 28 2008 — edited Mar 15 2008
Here i have and example of how the servers can be found and also how to extract information from the response.
This example only works for protcol HL1 (not source) and do not detect local games (if someone wants to do it...feel free)...

CSServerInfo.java
/**
 * Only HL1 servers info
 * @author Joaquin
 */
public class CSServerInfo {
    StringBuffer ipAndPort = new StringBuffer();
    StringBuffer serverName = new StringBuffer();
    StringBuffer map = new StringBuffer();
    StringBuffer gameDir = new StringBuffer();
    StringBuffer gameDesc = new StringBuffer();
    byte numPlayers;
    byte maxPlayers;
    byte netVersion;
    byte dedicated;
    byte os;
    byte password;
    byte isMod;
    ModData modInfo = new ModData();
    byte secure;
    byte numBots;
    
    private byte[] buffer;
    
    /** Creates a new instance of CSServerInfo */
    public CSServerInfo(byte[] buffer) {
	this.buffer = buffer;
	
	parseInformation();
    }
    
    public void parseInformation() {
	int index = 4;	    // Discard first 4 bytes
	
	char m = RawByteParser.parseChar(index, buffer);
	if (m != 'm')return;
	index++;
	
	index += RawByteParser.parseString(index, buffer, ipAndPort);
	index += RawByteParser.parseString(index, buffer, serverName);
	index += RawByteParser.parseString(index, buffer, map);
	index += RawByteParser.parseString(index, buffer, gameDir);
	index += RawByteParser.parseString(index, buffer, gameDesc);
	
	numPlayers = buffer[index];
	index++;
	maxPlayers = buffer[index];
	index++;
	netVersion = buffer[index];
	index++;
	dedicated = buffer[index];
	index++;
	os = buffer[index];
	index++;
	password = buffer[index];
	index++;
	isMod = buffer[index];
	index++;
	if (isMod == 1)modInfo.parse(buffer, index);
	index += modInfo.length();
	
	secure = buffer[index];
	index++;
	numBots = buffer[index];
	index++;
    }
    
    public String toString() {
	StringBuffer res = new StringBuffer("Server Info:\n");
	res.append("\nIP:        \t" + ipAndPort);
	res.append("\nName:     \t" + serverName);
	res.append("\nMap:       \t" + map);
	res.append("\nGame Dir:  \t" + gameDir);
	res.append("\nDesc:     \t" + gameDesc);
	res.append("\nPlayers:  \t" + numPlayers);
	res.append("\nMax Plyrs:\t" + maxPlayers);
	res.append("\nVersion:  \t" + netVersion);
	res.append("\nDedicated:\t" + (char)dedicated);
	res.append("\nOS:       \t" + (char)os);
	res.append("\nPassword: \t" + (int)password);
	//res.append("\nMod:  \t" + isMod);
	res.append("\n\t" + modInfo.toString().replaceAll("\n","\n\t"));
	res.append("\nSecure:  \t" + secure);
	res.append("\nNum Bots:\t" + numBots);
	return res.toString();
    }
}
CSServerScanner.java
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Vector;

/**
 *
 * @author Joaquin
 */
public class CSServerScanner implements Runnable {
    
    boolean __salir = false;
    int __port;
    Vector<CSServerInfo> servers = new Vector<CSServerInfo>();
    
    // if you know a better way of do this...please let me know.
    byte[] request = {(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x54,(byte)0x53,(byte)0x6F,(byte)0x75,(byte)0x72,(byte)0x63,(byte)0x65,(byte)0x20,(byte)0x45,(byte)0x6E,(byte)0x67,(byte)0x69,(byte)0x6E,(byte)0x65,(byte)0x20,(byte)0x51,(byte)0x75,(byte)0x65,(byte)0x72,(byte)0x79,(byte)0x00};
    
    public CSServerScanner( int port ) {
	__port = port;
    }
    
    public void scan() {
	Thread t = new Thread(this);
	t.setName("Scanner Thread");
	t.start();
    }
    
    public void stop() {
	__salir = true;
    }
    
    public void run() {
	try {
	    byte[] buf = new byte[255];
	    DatagramSocket socket = new DatagramSocket();	// Creamos el socket
	    DatagramPacket paquete = new DatagramPacket(buf,1);	// Creamos el paquete que se enviar� por broadcast
	    DatagramPacket paquete2 = new DatagramPacket(buf,255);	// Creamos el paquete para recibir datos
	    
	    socket.setBroadcast(true);
	    paquete.setAddress(InetAddress.getByName("255.255.255.255"));
	    paquete.setPort(__port);
	    paquete.setData(request);
	    
	    long d0 = System.nanoTime();
	    socket.send(paquete);
	    socket.setSoTimeout(200);
	    
	    while (!__salir) {
		try {
		    socket.receive(paquete2);
		    long d1 = System.nanoTime();// Cronometramos el tiempo que tard� en responder

		    // Now you have the response from server...do what you want...
		    System.out.println("Server Found at " + (d1-d0)/1000000 + " ms");
		    System.out.println("" + new CSServerInfo(paquete2.getData()).toString());
		    
		} catch (Exception e) {
		    //e.printStackTrace();
		}
	    }
	}  catch (Exception e) {
	    e.printStackTrace();
	}
    }
}
RawDataParser.java
/**
 *
 * @author Joaquin
 */
public class RawByteParser {
    
    /** Creates a new instance of RawByteParser */
    public RawByteParser() {
    }
    
    /**
     * Extracts a C formatted string out of the byte buffer. The buffer is not
     * affected by this method. The resulting string is stored into the StringBuffer.
     * @param	offset	Index of the first character of the string to be extracted
     * @param	data	Byte buffer where the string is.
     * @param	res	StringBuffer where the string will be stored
     * @return	the length of the extracted string plus the null character.
     */
    public static int parseString(int offset, byte[] data, StringBuffer res) {
	int i = offset;
	while (data[i] != 0) {
	    char c = RawByteParser.parseChar(i, data);
	    res.append(c);
	    i++;
	}
	return i - offset + 1;
    }
    
    /**
     * Read a long C value from the data buffer.
     * This method takes 4 bytes of the buffer and convert them into a single long.
     * The buffer is not affected by this method.
     * @param	offset	index of the first byte to be parsed
     * @param	data	byte buffer.
     * @return	the long value.
     */
    public static long parseLong(int offset, byte[] data) {
	long a = (data[offset]) & 0xffL;
	long b = (data[offset+1]<<8) & 0xff00L;
	long c = (data[offset+2]<<16) & 0xff0000L;
	long d = (data[offset+3]<<24) & 0xff000000L;
	
	long res = a + b + c + d;
	
	return res;
    }
    
    /**
     * Read a byte value from the data buffer and returns the unsigned representation.
     * The buffer is not affected by this method.
     * @param	offset	index of the first byte to be parsed
     * @param	data	byte buffer.
     * @return	the byte parsed.
     */
    public static byte	parseByte(int offset, byte[] data) {
	return (byte)(data[offset] & 0xff);
    }
    
    /**
     * Read a char value from the data buffer.
     * The buffer is not affected by this method.
     * @param	offset	index of the char to be parsed
     * @param	data	byte buffer.
     * @return	the char parsed.
     */
    public static char parseChar(int offset, byte[] data) {
	return (char)(data[offset] & 0xff);
    }
}
ModData.java
/**
 * This class is used to extract the information of the mod out of the byte stream.
 *
 * @author Joaquin
 */
public class ModData {
    
    private StringBuffer URLInfo = new StringBuffer();
    private StringBuffer URLDL = new StringBuffer();
    private long modVersion;
    private long modSize;
    private byte svOnly;
    private byte cldll;
    
    private int size = 0;
    
    /** Creates a new instance of ModData */
    public ModData() {
    }
    
    public void parse(byte[] data, int begin) {
	//URLInfodata
	int pos = begin;
	pos += RawByteParser.parseString(pos, data, URLInfo);
	pos += RawByteParser.parseString(pos, data, URLDL);
	pos++;	    // jump over the empty string ("\0");
	modVersion = RawByteParser.parseLong(pos, data);
	pos+=4;
	modSize = RawByteParser.parseLong(pos, data) / (1024*1024);	// in MB
	pos+=4;
	svOnly = data[pos];
	pos++;
	cldll = data[pos];
	pos++;
	
	size = pos - begin;
    }
    
    public int length() {
	return size;
    }

    public String toString() {
	StringBuffer res = new StringBuffer("ModiInfo:\n");
	res.append("\nURLInfo:   \t" + URLInfo);
	res.append("\nURLDL:     \t" + URLDL);
	res.append("\nVersion:   \t" + modVersion);
	res.append("\nSize:      \t" + modSize + " mb");
	res.append("\nServerSide:\t" + svOnly);
	res.append("\nCustom dll:\t" + cldll);
	return res.toString();
    }
}
Main.java
import java.util.Iterator;
import java.util.Vector;

/**
 *
 * @author Joaquin
 */
public class Main {
    
    /** Creates a new instance of Main */
    public Main() {
	Vector<CSServerScanner> scanners = new Vector<CSServerScanner>();
	
	/*
	 * Server's port ranges from 27015 to 27020
	 */
	for (int i=27015; i<27021; i++) {
	    CSServerScanner scanner = new CSServerScanner(i);
	    scanner.scan();
	    scanners.add(scanner);
	}
	
	// We wait for 2 secons...
	try {
	    Thread.sleep(2000);
	} catch (Exception e) {
	    e.printStackTrace();
	}
	
	// Close all the scanners
	Iterator<CSServerScanner> it = scanners.iterator();
	while (it.hasNext()){
	    it.next().stop();
	}
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
	new Main();
    }
}
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Apr 12 2008
Added on Jan 28 2008
5 comments
179 views