我正在编写一个程序,用php中的stream_socket_client连接到tcp服务器。我的问题是,如果我在执行任何额外的fwrites之前回显$ client对象的内容,页面就会挂起。目前,如果我在调用stream_get_contents之前发送所有请求,它会工作,但是一旦我调用stream_get_contents,它就像客户端不再响应一样?我会感谢任何帮助。
**编辑 这是我使用的API: https://www.onlinenic.com/cp_english/template_api/download/ONLINENIC_API2.0.pdf
**编辑
//see full code below
//------Client creation code, precho function
function getTESTClient($address, $port)
{
$client = stream_socket_client("$address:$port", $errno, $errorMessage);
if ($client === false) {
throw new UnexpectedValueException("Failed to connect: $errorMessage");
}
return $client;
}
function precho($s)
{
echo "<pre>";
echo $s;
echo "</pre>";
}
//-------Problem code
//$loginRequest, $domainAvailableRequest, and $logoutRequest - see full code below
//-----------------------------------------
$address = "www.somesite.com";//This is where I would fill in the address
$port = "12345";//This is where I would fill in the port
$client = getTESTClient($address, $port);
//-----------------------------------------
fwrite($client, $loginRequest);
precho(htmlspecialchars(stream_get_contents($client)));
fwrite($client, $domainAvailableRequest);
precho(htmlspecialchars(stream_get_contents($client)));
fwrite($client, $logoutRequest);
precho(htmlspecialchars(stream_get_contents($client)));
fclose($client);
//-------Alternative working code, if I read all responses at once...
//*But I want to be able to read each response individually...
fwrite($client, $loginRequest);
fwrite($client, $domainAvailableRequest);
fwrite($client, $logoutRequest);
precho(htmlspecialchars(stream_get_contents($client)));
fclose($client);
完整代码:
<?php
function getDomainType($ext)
{
$domaintypes = ['com'=>0, 'net'=>0, 'org'=>807, 'biz'=>800, 'info'=>805, 'us'=>806, 'in'=>808,
'mobi'=>903, 'eu'=>902, 'asia'=>905, 'me'=>906, 'name'=>804, 'tel'=>907, 'cc'=>[600,610], 'tv'=>400,
'tw'=>302, 'uk'=>901, 'co'=>908, 'xxx'=>930, 'pw'=>940, 'club'=>740, 'bike'=>2001, 'clothing'=>2002,
'guru'=>2003, 'holdings'=>2004, 'plumbing'=>2005, 'singles'=>2006, 'ventures'=>2007, 'camera'=>2008,
'equipment'=>2009, 'estate'=>2010, 'gallery'=>2011, 'graphics'=>2012, 'lighting'=>2013, 'photography'=>2014,
'construction'=>2015, 'contractors'=>2016, 'site'=>950, 'online'=>951, 'sex'=>936,
'directory'=>2017, 'kitchen'=>2018, 'land'=>2019, 'technology'=>2020, 'today'=>2021, 'diamonds'=>2022,
'enterprises'=>2023, 'tips'=>2024, 'voyage'=>2025, 'careers'=>2026, 'photos'=>2027,
'recipes'=>2028, 'shoes'=>2029, 'cab'=>2030, 'company'=>2031, 'domains'=>2032, 'limo'=>2033,
'academy'=>2034, 'center'=>2035, 'computer'=>2036, 'management'=>2037, 'systems'=>2038,
'builders'=>2039, 'email'=>2040, 'solutions'=>2041, 'support'=>2042, 'training'=>2043, 'camp'=>2044,
'education'=>2045, 'glass'=>2046, 'institute'=>2047, 'repair'=>2048, 'coffee'=>2049, 'florist'=>2050,
'house'=>2051, 'international'=>2052, 'solar'=>2053, 'marketing'=>2054, 'viajes'=>2055, 'farm'=>2056,
'codes'=>2057, 'cheap'=>2058, 'zone'=>2059, 'agency'=>2060, 'bargains'=>2061, 'boutique'=>2062,
'cool'=>2063, 'watch'=>2064, 'works'=>2065, 'expert'=>2066, 'foundation'=>2067, 'exposed'=>2068,
'villas'=>2069, 'flights'=>2070, 'rentals'=>2071, 'cruises'=>2072, 'vacations'=>2073, 'condos'=>2074,
'properties'=>2075, 'maison'=>2076, 'tienda'=>2077, 'dating'=>2078, 'events'=>2079, 'partners'=>2080,
'productions'=>2081, 'community'=>2082, 'catering'=>2083, 'cards'=>2084, 'cleaning'=>2085, 'tools'=>2086,
'industries'=>2087, 'parts'=>2088, 'supplies'=>2089, 'supply'=>2090, 'report'=>2091, 'vision'=>2092,
'fish'=>2093, 'services'=>2094, 'capital'=>2095, 'engineering'=>2096, 'exchange'=>2097, 'gripe'=>2098,
'associates'=>2099, 'lease'=>2100, 'media'=>2101, 'pictures'=>2102, 'reisen'=>2103, 'toys'=>2104,
'university'=>2105, 'town'=>2106, 'wtf'=>2107, 'fail'=>2108, 'financial'=>2109, 'limited'=>2110,
'care'=>2111, 'clinic'=>2112, 'surgery'=>2113, 'dental'=>2114, 'tax'=>2115, 'cash'=>2116,
'fund'=>2117, 'investments'=>2118, 'furniture'=>2119, 'discount'=>2120, 'fitness'=>2121, 'schule'=>2122,
'sexy'=>2500, 'tattoo'=>2501, 'link'=>2502, 'guitars'=>2503, 'gift'=>2504, 'pics'=>2505, 'photo'=>2506,
'christmas'=>2507, 'blackfriday'=>2508, 'hiphop'=>2509, 'juegos'=>2510, 'audio'=>2511, 'click'=>2512,
'hosting'=>2513, 'property'=>2514, 'top'=>770, 'porn'=>932, 'adult'=>934, 'city'=>2129, 'ceo'=>742];
if(isset($domaintypes[strtolower($ext)]))
{
return $domaintypes[strtolower($ext)];
}
return "unknown";
}
function getTCPClient()
{
}
function getTESTClient($address, $port)
{
$client = stream_socket_client("$address:$port", $errno, $errorMessage);
if ($client === false) {
throw new UnexpectedValueException("Failed to connect: $errorMessage");
}
return $client;
}
function uniqueInvoiceID()
{
$legend = "0123456789";
$len = 22;
$result = "";
for($i=0;$i<$len;$i++)
{
$result .= $legend[rand(0,9)];
}
return "client".$result;
}
function precho($s)
{
echo "<pre>";
echo $s;
echo "</pre>";
}
$clid = "135610";//OnlineNic's test account username
$clpass = "654123";//OnlineNic's test account password
$cltrid = uniqueInvoiceID();//Client Record ID/Invoice
echo $cltrid."<br><br>";
//md5(clid + md5(clpass) + cltrid + “login”)
$checkSumLogin = md5($clid.md5($clpass).$cltrid."login");//Checksum
$checkSumLogout = md5($clid.md5($clpass).$cltrid."logout");//Checksum
$loginRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
<request>
<category>client</category>
<action>Login</action>
<params>
<param name=\"clid\">$clid</param>
</params>
<cltrid>$cltrid</cltrid>
<chksum>$checkSumLogin</chksum>
</request>";
$logoutRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
<request>
<category>client</category>
<action>Logout</action>
<params>
<param name=\"clid\">$clid</param>
</params>
<cltrid>$cltrid</cltrid>
<chksum>$checkSumLogout</chksum>
</request>";
$checkDomain = "somedomain.com";
$ext = "com";
$dType = getDomainType($ext);
$requestID = uniqueInvoiceID();
$domainAvailChecksum = md5($clid.md5($clpass).$requestID."checkdomain".$dType.$checkDomain);
$domainAvailableRequest = "<?xml version=\"1.0\"?>
<request>
<category>domain</category>
<action>CheckDomain</action>
<params>
<param name=\"domaintype\">$dType</param>
<param name=\"domain\">$checkDomain</param>
</params>
<cltrid>$requestID</cltrid>
<chksum>$domainAvailChecksum</chksum>
</request>";
$client = getTESTClient("tcp://ote.onlinenic.com", "30009");
fwrite($client, $loginRequest);
precho(htmlspecialchars(stream_get_contents($client)));
fwrite($client, $domainAvailableRequest);
precho(htmlspecialchars(stream_get_contents($client)));
fwrite($client, $logoutRequest);
precho(htmlspecialchars(stream_get_contents($client)));
fclose($client);
?>
答案 0 :(得分:2)
stream_get_contents
的第二个参数是$maxlength
,即要读取的最大字节数。如果未设置(或传递默认值-1
),则会读取整个流,直到流的末尾。
这意味着stream_get_contents
将继续读取流中的所有数据,直到流不被另一端关闭为止。 (stream_get_contents
不知道你的协议的细节,所以它不能知道它“应该”在服务器的“一个响应”之后停止阅读;它没有任何关于甚至意味着什么的概念。)
这意味着,如果您的TCP连接上有查询响应协议,则必须stream_get_contents()
完全您要接收的数据长度(如果您确切知道的话)响应大小将是什么),或者你必须从服务器读取数据并自己处理它。
你究竟是怎么做的,这在很大程度上取决于你的协议。如果它是面向行的,您可以使用fgets($client)
一次检索一行。如果是二进制协议,则可以使用stream_get_contents($client, $sizeOfYourPacket)
。
由于您有一个基于XML的协议,您可能希望创建一个新函数来处理读取响应并理解XML,以便它知道要读取多少数据以及何时可以将响应(可能已经处理)发送回你的申请。
如果没有凭据,就很难看出服务器的确切行为,所以除此之外,您还需要进行实验。