The TcpClient class wrappers the networking details for reading/writing to a network stream into a simple, easy-to-use class (much like .NET TcpClient). An example use, connecting to a POP mail server, is attached. Change the POP server details and username/password at the top of the file to test.
By : wmfwlr
<!-- EXAMPLE SCRIPT USING CLASS -->
<font face="verdana" size="2">
<?
include('class.TcpClient.php');
//** Displays the error message given if there is non-empty text.
function ShowError($errortext)
{
if(strlen($errortext) > 0)
print("<font color='red'>$errortext</font><br>");
}
//** the POP server address, user account, and password to use for
//** testing client application. NOTE: your POP user name is your
//** full email address, unless the server is otherwise configured.
$PopServer = "popserver.yourdomain.com";
$PopUser = "email@yourdomain.com";
$PopPassword = "yourpassword";
//** connect to the POP server given on 110, the standard POP port.
//** Change this if necessary.
$client = new TcpClient($PopServer, 110);
//** set the default read/write timeout to 2 seconds (2000 ms).
$client->Timeout = 2000;
//** you can set the default newline character(s) used when sending data.
$client->NewLine = "\r\n";
//** connect to server and get any error message (if available).
$client->Connect();
ShowError($client->GetError());
//** get the mailserver greeting (one line).
print("<b>" . $client->ReadLine() . "</b><br>");
ShowError($client->GetError());
//** send user login info to the server.
print($client->WriteLine("USER $PopUser") . " bytes written<br>");
ShowError($client->GetError());
//** get the mailserver USER response message.
print("<b>" . $client->ReadLine() . "</b><br>");
ShowError($client->GetError());
//** send user account password to the server.
print($client->WriteLine("PASS $PopPassword") . " bytes written<br>");
ShowError($client->GetError());
//** get the mailserver PASS response message, login success
print("<b>" . $client->ReadLine() . "</b><br>");
ShowError($client->GetError());
//**!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//**!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//**
//** Put any other commands for the POP server here!
//** Full command list @ http://www.ietf.org/rfc/rfc1939.txt
//**
//**!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//**!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//** notify the mail server connection is closing.
print($client->WriteLine("QUIT") . " bytes written<br>");
ShowError($client->GetError());
//** get the mailserver farewell message.
print("<b>" . $client->ReadLine() . "</b><br>");
ShowError($client->GetError());
$client->Close();
?>
</font>
<?
//-- CLASS FILE FOR TCP CLIENT --
//** ©William Fowler (wmfwlr@cogeco.ca)
//** DECEMBER 22/2003, Version 1.0
if(isset($GLOBALS["tcpclientclass_php"])) { return; } //** include once.
$GLOBALS["tcpclientclass_php"] = 1; //** file included.
//** error code indicating that no connection is available.
define("TcpClientNoConnection", 0);
//** the default number of milliseconds to wait before timing out.
define("TcpClientDefaultTimeout", 30000);
//** the minimum buffer size for the TCP client class.
define("TcpClientMinBufferSize", 256);
//** the default newline character(s) used.
define("TcpClientNewLine", "\r\n");
//**!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//**TCP_CLIENT_CLASS_DEFINITION***********************************************
//** The TcpClient class encapsulates most networking communication details
//** into an easy-to-use wrapper. Connections are not persistant.
class TcpClient
{
//** (Integer) the internal underlying socket identifier.
var $Socket = TcpClientNoConnection;
//** (String) the name/IP of the remote host
var $Host;
//** (Integer) the port number to connect to remote host.
var $Port = 0;
//** (String) the last error that occurred (NULL if no error).
var $LastError = null;
//** (String) the newline character to be used when sending data.
var $NewLine = TcpClientNewLine;
//** (Integer) the size of the buffer used to receive data.
var $ReceiveBufferSize = TcpClientMinBufferSize;
//** (Integer) the number of milliseconds to wait before aborting a connect,
//** read, or write operation for the client.
var $Timeout = TcpClientDefaultTimeout;
//** creates a new TcpClient instance based on the hostname and port given.
function TcpClient($remoteHost=null, $portNum=0)
{
$this->Host = strval($remoteHost);
$this->Port = intval(max(0, $portNum)); //** ensure port >= than zero.
}
//** Returns: Boolean
//** Determine whether or not a connection to the remote host has been
//** established.
function isOpen()
{
return ($this->Socket ? true : false);
}
//** Returns: String
//** Get the last recorded error that occurred. If no error previously
//** occurred NULL is returned. The last error is cleared.
function GetError()
{
$theerror = $this->LastError;
$this->ClearError();
return $theerror;
}
//** Returns: None
//** Clear the last error stored for this client.
function ClearError()
{
$this->LastError = null;
}
//** Returns: Boolean
//** Attemept to connect to the client remote host on the port number given.
//** If no host is available FALSE is returned and no connection is made.
//** If FALSE is returned the last error is available from the 'GetError()'
//** method.
function Connect()
{
$this->ClearError(); //** clear any existing error messages.
//** no host name/IP has been set for this client, no connection can be made.
//** Store the appropriate error.
if(strlen(trim($this->Host)) == 0)
{
$this->LastError = "No remote host was provided";
return false;
}
//** attempt to connect to the host on the port given. Record any error number
//** and error message generated.
$errorNum = 0;
$this->Socket = fsockopen($this->Host, $this->Port, &$errorNum,
&$this->LastError, ($this->Timeout / 1000));
//** if there is no error given and the socket is valid connection is okay.
return ($this->isOpen() && strlen(trim($this->LastError)) == 0);
}
//** Returns: Boolean
//** Attempt to close the open client connection.
function Close()
{
//** no open cobnnection is available. Set error appropriately.
if(!$this->isOpen())
$this->LastError = "No connection available to close";
//** an open connection is available to close. Close underlying socket.
else
{
fclose($this->Socket); //** clsoe the connection.
$this->Socket = TcpClientNoConnection; //** no connection now.
}
return !$this->isOpen(); //** return the close operation success.
}
//** Returns: Integer
//** Attempt to write the data given to the underlying socket. The number of
//** bytes successfully written to the stream is returned. If no connection
//** is available 0 is returned, as no bytes were written.
function Write($data=null)
{
//** no connection is available, zero bytes can be sent.
if(!$this->isOpen())
{
$this->LastError = "No connection available for writing";
return 0;
}
$data = strval($data); //** ensure that data is available.
if(strlen($data) == 0) //** no data to be sent.
return 0; //** zero bytes were sent.
else //** connection and data, set timeout and send.
{
$this->_SetTimeout(); //** set timeout.
return fwrite($this->Socket, $data, strlen($data)); //** write data.
}
}
//** Returns: Integer
//** Attempt to write the data given to the underlying socket, followed by a
//** newline. The newline is defined by the '$this->NewLine' property. The
//** number of bytes actually written is returned.
function WriteLine($data=null)
{
return $this->Write($data . $this->NewLine);
}
//** Returns: String
//** Attempt to read the number of bytes given (or one by default) from the
//** connection. If no connection is available, the length given is zero or
//** negative, or an error occurs NULL is returned.
function Read($length=1)
{
if(intval($length) <= 0)
{
$this->LastError = "Cannot read zero or less bytes";
return null;
}
//** no connection is available to read from, no data can be read.
else if(!$this->isOpen())
{
$this->LastError = "No connection available for reading";
return null;
}
else //** a valid connection identifier is available.
{
$this->_SetTimeout(); //** ensure timeout is set.
return fread($this->Socket, $length); //** attempt to read n-bytes.
}
}
//** Returns: String
//** Attempt to read one full line from the underlying stream. If no
//** connection is available NULL is returned. Any newline characters
//** are included in the string returned.
function ReadLine()
{
//** no connection is available to read from, no data can be read.
if(!$this->isOpen())
{
$this->LastError = "No connection available for reading";
return null;
}
//** continue to read in data until a line ends with the newline character(s).
//** This is safe as the 'fgets()' function will not read past a newline
//** character. Ensure that the read buffer is at least the minumum size. If
//** one iteration is complete and no data was read in the socket blocking
//** expired. Stop reading at that point.
$streamdata = ""; //** no data to start with.
$sockethasexpired = false; //** initially no timeout experienced.
while(!$this->_EndsWithNewLine($streamdata) && !$sockethasexpired)
{
$this->_SetTimeout(); //** ensure socket timeout is set.
$streamdata .= fgets($this->Socket, max(TcpClientMinBufferSize,
$this->ReceiveBufferSize));
//** if ever at the point where reading has occurred and no data is available
//** a socket timeout has occurred. Exit the loop and set the error.
if(strlen($streamdata) == 0)
{
$sockethasexpired = true;
$this->LastError = "The read took longer than $this->Timeout ms";
}
}
return $streamdata; //** return the data received, including newline.
}
//** Returns: Boolean
//** Determine whether or not the string given ends with a newline character.
//** If no data is given FALSE is returned.
function _EndsWithNewLine($data=null)
{
$data = strval($data); //** ensure that data is a string.
if(strlen($data) == 0) //** no date given to test.
return false; //** does not end with newline.
//** get the position of the last newline character. If the value returned
//** is not numeric it is a boolean, indicating no match. Considered to end
//** with newline if it ends with either a '\n' or '\r' character.
$creturnpos = strrpos($data, "\r"); //** position of '\n'.
$newlinepos = strrpos($data, "\n"); //** position of '\r'.
return (is_int($newlinepos) || is_int($creturnpos));
}
//** Returns: None
//** Set the underlying socket timeout to the 'Timeout' value for this
//** instance. If not connected nothing is done.
function _SetTimeout()
{
//** if a connection is available set the socket timeout. Get the number of
//** seconds and microseconds form the instance 'Timeout' property.
if($this->isOpen())
{
stream_set_timeout($this->Socket, intval($this->Timeout / 1000),
intval(($this->Timeout % 1000) * 1000));
}
}
}
?>
| DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |
More Miscellaneous Code Articles
More By Codewalkers
developerWorks - FREE Tools! |
You'll get answers to many questions and more from David Barnes, Lead Evangelist for IBM Emerging Internet Technologies. David will discuss aspects of Web 2.0 that bring value to corporations, academia, and government. He'll also discuss IBM's vision around Web 2.0, including the importance of remixability and consumability. The discussion will culminate with examples of various IBM Software Group solutions you can use to get ahead of the Web 2.0 adoption curve. FREE! Go There Now!
|
|
|
|
Hear how IBM Rational Project and Portfolio Management integrated solutions help teams put the right tools and processes in place to maximize the effectiveness and efficiency of project teams and ensure that the business vision is being executed correctly. Learn how to automate and integrate requirements prioritization, top-down project planning, communications and controls, and methodology deployment to keep your scope, costs, and schedules under control. Tackle with an end-to-end approach the management of scope and scope changes, usage of methodology to control and empower project teams, and optimization of resources to align activity costs with the overall project plan. FREE! Go There Now!
|
|
|
|
Learn how you can extend modern application lifecycle management to IBM System z through the IBM Rational Software Delivery Platform (SDP). The Did you say mainframe? e-kit includes podcasts, webcasts, tutorials, white and red papers, demos, and articles designed to help ease the challenges of modernizing your enterprise. This complimentary kit for mainframe developers is a practical, how-to guide for making the most of an existing development environment, including the skills and infrastructure already in place at an established enterprise. FREE! Go There Now!
|
|
|
|
Download the Rational Application Developer (RAD) v7.5 open beta code and start developing applications for the JEE5 standard which features EJB3.0, JPA, JSF 1.2, JSP 2.1 and Servlet 2.5 standards. When you use this beta you will see how you can increase developer productivity for already existing applications with improved support for refactoring, as well as adding new features to existing applications. In addition, the beta provides tooling for JD Edwards, Oracle, SAP, Siebel and PeopleSoft to improve the developer productivity with these enterprise systems. FREE! Go There Now!
|
|
|
|
Visit IBM developerWorks to download a free trial of the latest release of IBM Lotus Sametime Standard V8.0. Lotus Sametime Standard V8.0 is a platform for unified communications and collaboration that combines security features with an extensible, open solution including integrated Voice over IP, geographic location awareness, mobile clients, and a robust Business Partner community offering telephony and video integration. FREE! Go There Now!
|
|
|
|
Join this webcast to see how IBM Data Studio Developer and pureQuery can take the pain out of Java data access. uApplications developed using both Java and SQL have become a common requirement. Database connectivity using Java Database Connectivity (JDBC) to create an application is a multi-step tedious process, and tooling that covers both SQL and Java has been unavailable, until now. IBM Data Studio introduces the pureQuery platform: a high-performance, Java data access platform focused on simplifying the tasks of developing, managing, and optimizing database applications and services. FREE! Go There Now!
|
|
|
|
Ken Krugler, co-founder of code search company Krugle, and Laura Merling, vice president of Marketing and Business Development for Krugle, join to talk about the ins and outs of code search and what it means as a new feature for developerWorks users. FREE! Go There Now!
|
|
|
|
Portfolio Management is about effectively managing portfolio value by aligning portfolio investments with business goals. This complimentary e-kit provides a collection of materials that can help you understand how IBM Rational enables and automates best practices for improved governance and clear visibility into portfolio and project performance across the entire IT project lifecycle. FREE! Go There Now!
|
|
|
|
Visit IBM developerWorks to try the IBM SOA Sandbox for people. The SOA Sandbox for people provides a trial environment with the necessary tooling and components required to enable consistent human and process interaction and collaboration, showing how you can improve user experience and business productivity. FREE! Go There Now!
|
|
|
|
User communities play an important role in communication and collaboration around products, solutions and other areas of special interest to members. Successful communities are able to provide the right mix of content and services to deliver a value proposition that resonates with each audience. Join Tom Inman, VP of Marketing for Information and Platform Solutions as he introduces the new LeverageINFORMATION community. During this webcast, learn about the value provided by the community and how customers and partners derive value from the community in addressing their own technical and business challenges. FREE! Go There Now!
|
|
|
|
All FREE IBM® developerWorks Tools! |