Using Network Streams
by Wei-Meng Lee07/07/2003
In my earlier article on .NET streams ("
.NET Streams Explained"), I talked about the various implementation of
the Stream class, such as the BufferedStream, FileStream, MemoryStream, and the
CryptoStream classes. One class that I did not discuss much is the
NetworkStream class.
In this article, I will discuss the use of the NetworkStream class for network
communication, and how easy it is to use it for socket programming.
Sending Text Using the NetworkStream Class
The first example that I will illustrate is building a simple client and server to show the exchange of text between two machines. For simplicity, I am writing a synchronous server and the server will simply send back whatever the client has sent it, much like the echo service defined in RFC 862. Also, I will use a VB.NET console application to further simplify the code example.
Building the Server
For all of the examples in this article, I need to import the following namespaces:
Imports System.Net.Sockets
Imports System.Net
Imports System.Text
Imports System.IO
Let's first build the server (in all my future articles I will show the complete code before I dissect them; this would be easier for readers to quickly plug-and-play the code into their projects):
Const portNo As Integer = 500
Dim localAdd As System.Net.IPAddress = _
IPAddress.Parse("127.0.0.1")
Dim listener As New TcpListener(localAdd, portNo)
listener.Start()
Console.WriteLine("Listening...")
Dim tcpClient As TcpClient = listener.AcceptTcpClient()
Dim NWStream As NetworkStream = tcpClient.GetStream
Dim bytesToRead(tcpClient.ReceiveBufferSize) As Byte
'---read incoming stream
Dim numBytesRead As Integer = NWStream.Read(bytesToRead, 0, _
CInt(tcpClient.ReceiveBufferSize))
Console.WriteLine("Received :" & _
Encoding.ASCII.GetString(bytesToRead, 0, numBytesRead))
'---write back the text
Console.WriteLine("Sending back : " & _
Encoding.ASCII.GetString(bytesToRead, 0, numBytesRead))
NWStream.Write(bytesToRead, 0, numBytesRead)
tcpClient.Close()
listener.Stop()
Console.ReadLine()
The first few lines are straightforward; set up a TcpListener object and listen
at the local port at port 500. Note that the TcpListener constructor in .NET
1.1 now requires the local address to be passed in as a parameter (the old
constructor that simply takes in a port number is now obsolete). You can use
the IPAddress.Parse() method (from the System.Net namespace) to convert an IP
address in string format to the format required by the IPAddress class:
Const portNo As Integer = 500
Dim localAdd As System.Net.IPAddress = _
IPAddress.Parse("127.0.0.1")
Dim listener As New TcpListener(localAdd, portNo)
listener.Start()
Console.WriteLine("Listening...")
Dim tcpClient As TcpClient = listener.AcceptTcpClient()
Once a connection is established, create an instance of the NetworkStream class
and use the GetStream() method of the TcpClient class to return a NetworkStream
object. Also declare a byte array to store the text sent by the client:
Dim NWStream As NetworkStream = tcpClient.GetStream
Dim bytesToRead(tcpClient.ReceiveBufferSize) As Byte
You can read the incoming data sent by the client using the Read() method of
the NetworkStream class (all incoming data are stored in a byte array). This
method returns the number of total bytes read. Once the data is received, I
used the Encoding.ASCII.GetString() method from the System.Text namespace to
convert the byte array to string and display it on the screen:
'---read incoming stream
Dim numBytesRead As Integer = NWStream.Read(bytesToRead, 0, _
CInt(tcpClient.ReceiveBufferSize))
Console.WriteLine("Received :" & _
Encoding.ASCII.GetString(bytesToRead, 0, numBytesRead))
Once the data is read, I will sent it back to the client using the Write()
method of the NetworkStream class:
'---write back the text
Console.WriteLine("Sending back : " & _
Encoding.ASCII.GetString(bytesToRead, 0, numBytesRead))
NWStream.Write(bytesToRead, 0, numBytesRead)
Finally, close the TcpClient object and stop the TcpListener object:
tcpClient.Close()
listener.Stop()
Console.ReadLine()
Building the client
With the server built, let's now build the client. Here is the code for the client:
Const portNo = 500
Const textToSend = "1234567890098765432111"
Dim tcpclient As New System.Net.Sockets.TcpClient
tcpclient.Connect("127.0.0.1", portNo)
Dim NWStream As NetworkStream = tcpclient.GetStream
Dim bytesToSend As Byte() = Encoding.ASCII.GetBytes(textToSend)
'---send the text
Console.WriteLine("Sending : " & textToSend)
NWStream.Write(bytesToSend, 0, bytesToSend.Length)
'---read back the text
Dim bytesToRead(tcpclient.ReceiveBufferSize) As Byte
Dim numBytesRead = NWStream.Read(bytesToRead, 0, _
tcpclient.ReceiveBufferSize)
Console.WriteLine("Received : " & _
Encoding.ASCII.GetString(bytesToRead, 0, _
numBytesRead))
Console.ReadLine()
tcpclient.Close()
If you compare the code for the client with that of the server, you will notice that they are very similar. So I won't go into details here.
To test the sample applications, run the server application followed by the client. You should see something like this:
|
| Figure 1. Sending and receiving of data by the client and the server |
Receiving Large Incoming Data
In the previous example, I used the constant ReceiveBufferSize (which is 8192
bytes) as the maximum number of bytes to read as incoming text:
Dim bytesToRead(tcpClient.ReceiveBufferSize) As Byte
'---read incoming stream
Dim numBytesRead As Integer = NWStream.Read(bytesToRead, 0, _
CInt(tcpClient.ReceiveBufferSize))
What happen if the incoming data is more than the size you have defined? In the next example, I will simulate reading a long string of text by reading 10 bytes at a time. Here is my modified server:
Const BUFFER_SIZE As Integer = 10
Dim bytesToRead(BUFFER_SIZE) As Byte
'---read incoming stream
Dim textReceived As String
Do
Dim numBytesRead As Integer = _
NWStream.Read(bytesToRead, 0, BUFFER_SIZE)
textReceived += Encoding.ASCII.GetString(bytesToRead, _
0, numBytesRead)
Console.WriteLine("Received :" & _
Encoding.ASCII.GetString(bytesToRead, _
0, numBytesRead))
Loop Until Not NWStream.DataAvailable
'---write back the text
Console.WriteLine("Sending back : " & textReceived)
NWStream.Write(Encoding.ASCII.GetBytes(textReceived), 0, _
textReceived.Length)
Instead of reading all of the incoming data at once, I will read 10 bytes at a
time by using a loop. The DataAvailable property from the NetworkStream class
will indicate whether additional data is available on the stream object. If it
is, I will continue the read process until no more data is available.
If you run the server and the client, you should see the following:
|
| Figure 2. Receiving data in "blocks" |
Sending and Receiving Binary Data
The last example that I want to illustrate is to show how to send binary data
using the NetworkStream class.
Here is the complete source:
Const portNo As Integer = 500
Dim localAdd As System.Net.IPAddress = _
IPAddress.Parse("127.0.0.1")
Dim listener As New TcpListener(localAdd, portNo)
listener.Start()
Console.WriteLine("Listening...")
Dim tcpClient As TcpClient = listener.AcceptTcpClient()
Dim NWStream As NetworkStream = tcpClient.GetStream
Dim bytesToRead(tcpClient.ReceiveBufferSize) As Byte
'---read incoming stream
Dim numBytesRead As Integer = NWStream.Read(bytesToRead, _
0, CInt(tcpClient.ReceiveBufferSize))
'---write the bytes to file
Const FILE_NAME = "c:\image.gif"
Dim fs As System.IO.FileStream
fs = New FileStream(FILE_NAME, FileMode.CreateNew, _
FileAccess.Write)
fs.Write(bytesToRead, 0, numBytesRead)
fs.Close()
tcpClient.Close()
listener.Stop()
Console.ReadLine()
Similar to the last example, once I have read the incoming data into the byte array:
'---read incoming stream
Dim numBytesRead As Integer = NWStream.Read(bytesToRead, _
0, CInt(tcpClient.ReceiveBufferSize))
I save the read data into a file using the FileStream object (which I have
covered in the ".NET Streams Explained" article):
'---write the bytes to file
Const FILE_NAME = "c:\image.gif"
Dim fs As System.IO.FileStream
fs = New FileStream(FILE_NAME, FileMode.CreateNew, _
FileAccess.Write)
fs.Write(bytesToRead, 0, numBytesRead)
fs.Close()
Here is the code for the client:
Const portNo = 500
Const FILE_NAME = "c:\ondotnet_logo.gif"
Dim tcpClient As New System.Net.Sockets.TcpClient
tcpClient.Connect("127.0.0.1", portNo)
Dim NWStream As NetworkStream = tcpclient.GetStream
Dim bytesToSend(tcpClient.ReceiveBufferSize) As Byte
Dim fs As FileStream
fs = New FileStream(FILE_NAME, FileMode.Open, _
FileAccess.Read)
Dim numBytesRead As Integer = fs.Read(bytesToSend, _
0, bytesToSend.Length)
fs.Close()
'---send the text
Console.WriteLine("Sending ...")
NWStream.Write(bytesToSend, 0, numBytesRead)
Console.ReadLine()
tcpclient.Close()
As on the server, I used the FileStream class to open a file and read the
data to be sent.
Things to Note About the NetworkStream Class
Unlike most other Stream implementations, the use of the NetworkStream class is
more restrictive. For example, the CanSeek() properties of the NetworkStream
class are not supported and always return false. Similarly, the Length() and
Position() properties will throw a NotSupportedException.
Likewise, it is not possible to perform a Seek() operation, and the SetLength()
method will also throw a NotSupportedException.
On the other hand, the NetworkStream class has made network programming very
easy and encapsulates much of the complexity of socket programming. Developers
who are familiar with streams programming can use the NetworkStream class with
ease.
Wei-Meng Lee (Microsoft MVP) http://weimenglee.blogspot.com is a technologist and founder of Developer Learning Solutions http://www.developerlearningsolutions.com, a technology company specializing in hands-on training on the latest Microsoft technologies.
Return to ONDotnet.com
-
resending
2009-03-03 09:32:04 sirob [View]
-
resending
2009-03-03 09:31:55 sirob [View]
-
.Net Framework
2009-02-19 22:07:45 SBL Software Development [View]
-
Difference String & BinaryFile
2006-01-26 18:07:21 vitoto [View]
-
Source Code
2005-10-20 16:49:15 vitoto [View]
- Trackback from http://blog.csdn.net/jimmyxing/archive/2004/10/28/156501.aspx
C#ä¸å¼åWindows Servcieï¼by Wei-Meng Leeï¼
2004-10-27 22:36:15 [View]
-
Large Files
2004-09-27 05:02:43 Sefai [View]
-
Re:Large Files
2006-10-26 11:31:32 vaibe [View]
-
Graphics
2003-12-05 20:32:56 anonymous2 [View]
-
Graphics
2003-07-23 19:53:22 anonymous2 [View]

