Code: Select all
,Code: Select all
and [syntax="..."] tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read: [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]
Ok, I have got the biggest migraine right now from trying to figure this out.
The programs purpose is to send a group of files (info stored in an array) through custom ports via PHP's socket functions.
So I have it split in 3 parts. I only have a problem with 2.
Server.php is the master socket server. Clients connect, login and get redirected to a different port to upload their file (or other purpose when I get them). This works fine.
Client.php first retrieves settings from a database (via a specifically constructed web page) then Logs in to the master socket server which redirects it to another port (and script clientbackup.php) to handle file upload
clientbackup.php first receives a confirmation login from the client (to make sure its the right computer on the right port) it then reads the socket in infinite loop (broken by null) an initialization string "--sending file|filename|filedata|etc|etc" which starts a second loop. While in this loop the client should (and is) sending the contents of the file and the server is writing the file packet by packet as they come in. The problem I have is properly escaping out of this loop without an error.
I am currently using socket_write and socket_read due to socket_send and socket_recv's incredibly poor documentation. (Write and Read are bad too, but they are a bit simpler).
Is what is happening is that the EOF tag I created (because despite my greatest efforts I couldn’t find no single byte character that didn’t exist in any file) is getting appended to the end of the file. Basically the last packet of the file is well below the socket_recv packet size and so it keeps reading until the eof is sent. I had, at one point, checked for the existence of the eof tag in string, and if exist, remove it then write the string to the file close, etc. however then the problem comes if the read ends part way through the tag (ie it reaches 1024 bytes at %%##%%##EO and F##%%##%% ends up as part of the next line)
If anyone has any insight as to a work around (FTP is not an acceptable solution) I would really appreciate it. I have a feeling that somehow the flags with send and recv might make the difference, but I can’t seem to pin down much information about them.
Here is the server code relevant to the file transfer.Code: Select all
$fileTransfering = true;
while($fileTransfering) {
$input = socket_read($client,1024);
$input = str_replace(chr(0),'',$input);
echo $input."\n";
if ($input == 'Finished Transfer') {
$fileTransfering = false;
} elseif (strpos($input,"checkDB")) {
echo "enter Hash Check\n";
$subPath = str_replace('--checkDB|','',$input);
$filePath = $root.$subPath;
$fID = 'fid_'.md5($filePath);
$q = "select hash from scr_backuprecords where fileId = '$fID' && computerID = '$computerId'";
$res = mysql_query($q) or die("Error:$q");
$row = mysql_fetch_row($res);
$chkHash = $row[0].chr(0);
socket_write($client,$chkHash,1024);
} elseif (strpos($input,"Sending File")) { //if File transfer
//seperate file information
$fileArray = explode('|',$input);
$file = $fileArray[1];
$path = $fileArray[2];
$hash = $fileArray[3];
$size = $fileArray[4];
$time = $fileArray[5];
$fileTransfer = true; //set fileTransfering to true
$filePath = $root.$path.'/'.$file; //set filepath
if(!is_dir($root.$path)) { //check if destination directory exists
$subPaths = explode('/',$path); // seperate directories into an array
$creationPath = $root; // don't override $root
foreach($subPaths as $subPath) {
$creationPath .= $subPath.'/'; //setup next dir test/creation
if(!is_dir($creationPath)) mkdir($creationPath); //if subdir does not exist, create here
}
}
$fp = fopen($filePath,'wb');
socket_write($client,'--ready for file--',1000);
while($fileTransfer) {
$data = socket_read($client , 1024, PHP_BINARY_READ);
if ($data == '&&%%&&%%EOF%%&&%%&&'.chr(0) || !$data) {
echo "close $file\n";
fclose($fp);
$fileId = 'fid_'.md5($filePath); //Id is hashed filepath,
$localPath = substr($path,0,1).':'.substr($path,1);
$checkHash = md5_file($filePath);
socket_write($client,$checkHash,strlen($checkHash));
if($hash == $checkHash) {
echo "File Transfer of $file from $name Good\n";
$transferGood = 1;
} else {
echo "File Transfer of $file from $name Failed\n";
echo "Original Hash=$hash\nUploaded Hash=$checkHash\n";
$localPathMsg = strreplace('/','\\',$localPath);
$failMsg .= "$localPathMsg\\$file\n";
$transferGood = 0;
}
$q = "select fileId from scr_backuprecords where fileId = '$fileId';";
$res = mysql_query($q) or die("bad query: $q\n".mysql_error());
$row = mysql_fetch_row($res);
$file = addslashes($file);
$localPath = addslashes($localPath);
$path = addslashes($path);
if($row[0]) { //run test if record exists for this file
$q = "update scr_backuprecords set computerId = '$computerId', localPath = '$localPath', remotePath='$root$path', fileName = '$file', size = '$size', time = '$time', hash = '$hash', transferGood = $transferGood where fileId = '$fileId'";
} else {
$q = "insert into scr_backuprecords set fileId = '$fileId', computerId = '$computerId', localPath = '$localPath', remotePath='$root$path', fileName = '$file', size = '$size', time = '$time', hash = '$hash', transferGood = $transferGood";
}
mysql_query($q) or die("bad query: $q\n".mysql_error());
$fileTransfer = false;
break;
} else {
fwrite($fp,$data);
}
}
} elseif ($input == null) {
echo "null\n";
$filetransfering = false;
break 2;
}
}
And here is the client side code that is relevant
$sendingFile = true;
$sendingAttemptCount = 1;
while($sendingFile) {
$sendFile = "--Sending File|$file|$sendPath|$hash|$size|$time".chr(0); //set sending file tag
echo " $file\n";
socket_write($upload_socket,$sendFile,strlen($sendFile)); //send file info to be parsed by server
$response = socket_read($upload_socket,1000);
if(!strpos($response,'ready')) break;
//sleep(1); //required to prevent concatination
$fp = fopen($path.$file,'rb'); //open file to send
while (!feof($fp)) {
$in = fread($fp,1024);
socket_write($upload_socket, $in, strlen($in));
} //end file reading loop
sleep(1);
$eof = '&&%%&&%%EOF%%&&%%&&'.chr(0); //set eof tag
socket_write($upload_socket,$eof,strlen($eof)); //send end of file
$checkHash = socket_read($upload_socket,1024);
if ($hash == $checkHash) {
echo "Transfer of $file Good\n";
$iniFile = fopen($path.'SageBackupSettings.ini','a');
$writeText = "$file|$size|$time|$hash\n";
fwrite($iniFile,$writeText);
fclose($iniFile);
$sendingFile = false;
$process = "This is a special http request with a get variable that is used to update the database";
$handle = fopen($process, "r");
} else {
echo "Transfer of $file Bad\n$hash\n$checkHash\n";
$bitesSent = $sendingAttemptCount * $size;
if ($bitesSent > 10737418240) $sendingFile = false;
$sendingAttemptCount++;
}
}The Ninja Space Goat | Please use
Code: Select all
,Code: Select all
and [syntax="..."] tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read: [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]