Code:Server bandwidthdetection updated
From Red5Tutorials
After trying the original code written by Dan Rossi (see here), I shortened the code and also added upload speed dectection. (9th September 2009)
[edit]
Red5
Calling example
public boolean appConnect(IConnection conn) {
BandwidthDetection detect = new BandwidthDetection();
detect.checkBandwidth(conn);
}
Class IBandwidthDetection.java
import org.red5.server.api.IConnection;
public interface IBandwidthDetection {
public void checkBandwidth(IConnection p_client);
public void calculateClientBw(IConnection p_client);
}
Class BandwidthDetection.java:
import org.red5.server.adapter.MultiThreadedApplicationAdapter;
import org.red5.server.api.IConnection;
import org.red5.server.api.service.IPendingServiceCall;
import org.red5.server.api.service.IPendingServiceCallback;
import org.red5.server.api.service.IServiceCapableConnection;
import org.apache.log4j.Logger;
public class BandwidthDetection implements IPendingServiceCallback, IBandwidthDetection {
//---------------------------------------------------------
protected IConnection conn;
protected Logger log = Logger.getLogger(MultiThreadedApplicationAdapter.class);
protected boolean checkLatency = false;
protected double latency = 0;
protected Long writtenOffset;
protected Long readOffset;
protected Long bwStart;
//---------------------------------------------------------
public BandwidthDetection(){
//...
}
public void checkBandwidth(IConnection conn){
// Start checking
this.conn = conn;
// Reset
this.checkLatency = false;
this.latency = 0;
// Calc latency
this.getLatency();
}
protected void getLatency(){
// Update flag
this.checkLatency = true;
// Update start
this.bwStart = System.currentTimeMillis();
// Send packet
this.sendPacket(1);
}
protected void sendPacket(int numBytes){
try{
// Send
this.callBWCheck(new byte[numBytes]);
}catch (Exception e){
// Error
log.error(e.getMessage());
}
}
public void calculateClientBw(IConnection conn){
try{
// Update
this.writtenOffset = this.conn.getWrittenBytes();
this.readOffset = this.conn.getReadBytes();
// Update start
this.bwStart = System.currentTimeMillis();
// Send packet
this.sendPacket(1024);
}catch (Exception e){
// Error
log.error(e.getMessage());
}
}
/**
* Handle callback from service call.
*/
public void resultReceived(IPendingServiceCall call) {
try{
// Check flag
if(this.checkLatency){
// Update flag
this.checkLatency = false;
// Store latency
this.latency = ((double)(System.currentTimeMillis() - this.bwStart)) / 1000.00;
// Start BW check
this.calculateClientBw(this.conn);
}
// Check time
if((System.currentTimeMillis() - this.bwStart) < 1000){
// Send another packet
this.sendPacket(1024);
}else{
// Get total time
double totalTime = (System.currentTimeMillis() - this.bwStart);
// Work out bandwidth
this.callBWDone(Math.round(((this.conn.getWrittenBytes() - this.writtenOffset) * 8) / totalTime), Math.round(((this.conn.getReadBytes() - this.readOffset) * 8) / totalTime), this.latency);
}
}catch (Exception e){
// Error
log.error(e.getMessage());
}
}
private void callBWCheck(Object params){
try{
if(this.conn instanceof IServiceCapableConnection) {
((IServiceCapableConnection) this.conn).invoke("onBWCheck", new Object[]{params}, this);
}
}catch (Exception e){
// Error
log.error(e.getMessage());
}
}
private void callBWDone(double kbpsDown, double kbpsUp, double latency){
try{
if(this.conn instanceof IServiceCapableConnection) {
((IServiceCapableConnection) this.conn).invoke("onBWDone", new Object[]{kbpsDown, kbpsUp, latency});
}
}catch (Exception e){
// Error
log.error(e.getMessage());
}
}
}
[edit]
Flex / AS3
Client Side:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="onAppComplete()" width="602" height="211"> <mx:Script> <![CDATA[ import flash.utils.ByteArray; import flash.net.Responder; import flash.net.NetConnection; //----------------------------------------------------------------------- protected var nc:NetConnection; protected var serverURL:String = "rtmp://www.YourRed5Server.org/bwcheck"; //----------------------------------------------------------------------- protected var uploading:Boolean = false; protected var uploadPacket:ByteArray; //----------------------------------------------------------------------- protected function onAppComplete():void{ // Create upload packet this.uploadPacket = new ByteArray(); this.uploadPacket.length = 1024; // Create connection this.nc = new NetConnection(); this.nc.client = this; this.nc.connect(serverURL); } protected function onUploadResponse(event:Object):void{ try{ // Check flag if(this.uploading){ // Write this.nc.call("uploadTest", new Responder(this.onUploadResponse), this.uploadPacket); } }catch(e:Error){ // Error } } public function onBWCheck(obj:Object):void{ // Check upload if(!this.uploading){ // Update flag this.uploading = true; // Write this.nc.call("uploadTest", new Responder(this.onUploadResponse), this.uploadPacket); } } public function onBWDone(kbpsDown:Number, kbpsUp:Number, latency:Number):void{ // Update flag this.uploading = false; // Log this.txtLog.text = "kbpsDown: " + kbpsDown + "\n"; this.txtLog.text += "kbpsUp: " + kbpsUp + "\n"; this.txtLog.text += "Latency: " + latency; } ]]> </mx:Script> <mx:TextArea x="0" y="0" width="602" height="211" id="txtLog"/> </mx:Application>

