Imports System.Net.Sockets Imports System.Net Imports System.Text Imports System.IO우선 에코 서버부터 만들어보자. (필자는 먼저 완전한 소스 코드를 보여준 다음, 코드를 자세히 설명할 생각이다. 이와 같은 방식은 독자들이 자신의 프로젝트에 코드를 더 쉽게 추가하고 테스트할 수 있게 해준다.)
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()소스 코드의 첫번째 부분은 TcpListener 객체를 설정하고 500번 포트를 사용하여 로컬호스트에서 요청을 대기(listen)한다. 닷넷 1.1에서는 TcpListener 생성자에 매개변수로 로컬 주소를 사용해야 한다(포트 번호만 사용하던 생성자는 이제 폐기되었다). IPAddress 클래스를 사용하기 위해 System.Net 네임 스페이스의 IPAddress.Parse() 메소드를 사용하여 문자열 형식으로 된 주소를 IP 형식으로 변환한다.
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()접속이 이루어지면 TcpClient 클래스의 GetStream() 메소드를 사용하여 NetworkStream 클래스의 인스턴스를 생성하고 클라이언트에서 받아온 텍스트를 저장하기 위해 바이트 배열을 선언한다.
Dim NWStream As NetworkStream = tcpClient.GetStream Dim bytesToRead(tcpClient.ReceiveBufferSize) As ByteNetworkStream 클래스의 Read() 메소드는 클라이언트에서 보낸 데이터를 받아오며 이는 모두 바이트 배열로 저장된다. Read() 메소드의 반환값은 읽어온 문자 길이가 된다. 데이터를 받아온 다음에는 System.Text 네임스페이스의 Encoding.ASCII.GetString() 메소드로 바이트 배열을 문자열로 변환한 후 화면에 표시한다.
"---read incoming stream Dim numBytesRead As Integer = NWStream.Read(bytesToRead, 0, _ CInt(tcpClient.ReceiveBufferSize)) Console.WriteLine("Received :" & _ Encoding.ASCII.GetString(bytesToRead, 0, numBytesRead))일단 데이터가 읽히면 NetworkStream 클래스의 Write() 메소드를 사용해서 받아온 데이터를 클라이언트에 돌려준다.
"---write back the text Console.WriteLine("Sending back : " & _ Encoding.ASCII.GetString(bytesToRead, 0, numBytesRead)) NWStream.Write(bytesToRead, 0, numBytesRead)마지막으로 TcpClient 객체를 닫고, TcpListener 객체를 중지한다.
tcpClient.Close() listener.Stop() Console.ReadLine()에코 클라이언트 만들기
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()에코 클라이언트에서 사용된 코드와 서버에서 사용된 코드를 비교해보면 거의 똑같다는 것을 알 수 있다. 따라서 여기서는 자세한 설명은 생략하기로 하겠다. 예제 응용 프로그램을 테스트 하기 위해 일단 서버 응용 프로그램을 실행한 후 클라이언트를 실행해야 한다. 실행한 결과화면은 다음과 같다.
[그림 1] 클라이언트와 데이터에 의한 데이터 송수신
Dim bytesToRead(tcpClient.ReceiveBufferSize) As Byte "---read incoming stream Dim numBytesRead As Integer = NWStream.Read(bytesToRead, 0, _ CInt(tcpClient.ReceiveBufferSize))수신된 데이터가 설정한 버퍼 보다 크면 어떻게 될까? 다음 예제에서는 한 번에 10 바이트씩 읽어오면서 매우 긴 텍스트를 읽어오는 경우를 실험해보자.
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)위 예제는 수신된 데이터를 한 번에 모두 읽어오는 대신, 루프를 사용하여 한 번에 10 바이트씩 읽어온다. NetworkStream 클래스의 DataAvailable 속성은 이미 받아놓은 데이터가 소켓 내부에 있는지 없는지를 알려준다. 만약 소켓 내부에 이미 받아 놓은 데이터가 있으면 데이터가 없을 때까지 읽기를 계속 진행한다. 서버와 클라이언트를 실행하면 다음 결과를 볼 수 있다.
[그림 2] "블록" 내에서 데이터 수신
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()마지막 예제와 마찬가지로 받아놓은 데이터를 바이트 배열로 읽어들인다.
"---read incoming stream Dim numBytesRead As Integer = NWStream.Read(bytesToRead, _ 0, CInt(tcpClient.ReceiveBufferSize))FileStream 객체를 사용하여 읽어온 데이터를 파일로 저장한다.(이에 대한 것은 이전 기사(.NET Streams Explained)에서 다루었다)
"---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()클라이언트 코드는 다음과 같다.
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()서버와 마찬가지로 FileStream 클래스를 사용하여 파일을 열고 수신된 데이터를 받아온다.
최신 콘텐츠