컴퓨터네트워크

Similar documents
컴퓨터네트워크

Microsoft PowerPoint - 04-UDP Programming.ppt

Microsoft PowerPoint - Supplement-03-TCP Programming.ppt [호환 모드]

Microsoft PowerPoint - 03-TCP Programming.ppt

The Pocket Guide to TCP/IP Sockets: C Version

3ÆÄÆ®-11

<4D F736F F F696E74202D E20B3D7C6AEBFF6C5A920C7C1B7CEB1D7B7A1B9D62E >

Microsoft PowerPoint - Lecture_Note_5.ppt [Compatibility Mode]

Microsoft PowerPoint - CSharp-15-채팅

The Pocket Guide to TCP/IP Sockets: C Version

2009년 상반기 사업계획

The Pocket Guide to TCP/IP Sockets: C Version

Microsoft PowerPoint - 09-EDU-15-채팅 프로그래밍

PowerPoint Presentation

Microsoft PowerPoint - CSharp-10-예외처리

The Pocket Guide to TCP/IP Sockets: C Version

bn2019_2

<4D F736F F F696E74202D20C1A63235C0E520B3D7C6AEBFF6C5A920C7C1B7CEB1D7B7A1B9D628B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

Microsoft Word - Crackme 15 from Simples 문제 풀이_by JohnGang.docx

제1장 Unix란 무엇인가?

PowerPoint 프레젠테이션

JAVA 프로그래밍실습 실습 1) 실습목표 - 메소드개념이해하기 - 매개변수이해하기 - 새메소드만들기 - Math 클래스의기존메소드이용하기 ( ) 문제 - 직사각형모양의땅이있다. 이땅의둘레, 면적과대각

자바-11장N'1-502

PowerPoint Presentation

<4D F736F F F696E74202D20B3D7C6AEBFF6C5A9C7C1B7CEB1D7B7A1B9D65F FBCD2C4CF5FC3A4C6C35FBFA1C4DA2E BC8A3C8A

JAVA PROGRAMMING 실습 08.다형성

Microsoft PowerPoint - java1-lab5-ImageProcessorTestOOP.pptx

PowerPoint Presentation

<C0CCBCBCBFB52DC1A4B4EBBFF82DBCAEBBE7B3EDB9AE2D D382E687770>

PowerPoint Presentation

쉽게 풀어쓴 C 프로그래밍

PowerPoint 프레젠테이션

슬라이드 1

12-file.key

API 매뉴얼

À©µµ³×Æ®¿÷ÇÁ·Î±×·¡¹Ö4Àå_ÃÖÁ¾

Microsoft PowerPoint - Lecture_Note_7.ppt [Compatibility Mode]

PowerPoint Presentation

JMF3_심빈구.PDF

Network Programming

Microsoft PowerPoint - ch07 - 포인터 pm0415

<4D F736F F F696E74202D20BBB7BBB7C7D15F FBEDFB0A3B1B3C0B05FC1A638C0CFC2F72E BC8A3C8AF20B8F0B5E55D>

C++ Programming

Microsoft PowerPoint - C++ 5 .pptx

gnu-lee-oop-kor-lec06-3-chap7

제11장 프로세스와 쓰레드

PowerPoint Presentation

(Microsoft PowerPoint - 07\300\345.ppt [\310\243\310\257 \270\360\265\345])

<4D F736F F F696E74202D20C1A63038C0E520C5ACB7A1BDBABFCD20B0B4C3BC4928B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

<4D F736F F F696E74202D20C1A63234C0E520C0D4C3E2B7C228B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

PowerPoint Presentation

Microsoft PowerPoint 자바-기본문법(Ch2).pptx

PowerPoint 프레젠테이션

rmi_박준용_final.PDF

02 C h a p t e r Java

어댑터뷰

PowerPoint Presentation

PowerPoint 프레젠테이션

JAVA PROGRAMMING 실습 05. 객체의 활용

게시판 스팸 실시간 차단 시스템

PowerPoint 프레젠테이션

vi 사용법

adfasdfasfdasfasfadf

13-Java Network Programming

Microsoft PowerPoint PythonGUI-socket

Microsoft PowerPoint - 13 ¼ÒÄÏÀ» ÀÌ¿ëÇÑ Åë½Å 2.ppt

초보자를 위한 C# 21일 완성

Microsoft PowerPoint - Java7.pptx

PowerPoint 프레젠테이션

Microsoft PowerPoint - 2강

JAVA PROGRAMMING 실습 09. 예외처리

Microsoft PowerPoint - 12 ¼ÒÄÏÀ» ÀÌ¿ëÇÑ Åë½Å 1.ppt

(Microsoft PowerPoint - java1-lecture11.ppt [\310\243\310\257 \270\360\265\345])

1. 객체의생성과대입 int 형변수 : 선언과동시에초기화하는방법 (C++) int a = 3; int a(3); // 기본타입역시클래스와같이처리가능 객체의생성 ( 복습 ) class CPoint private : int x, y; public : CPoint(int a

2) 활동하기 활동개요 활동과정 [ 예제 10-1]main.xml 1 <LinearLayout xmlns:android=" 2 xmlns:tools="

파일로입출력하기II - 파일출력클래스중에는데이터를일정한형태로출력하는기능을가지고있다. - PrintWriter와 PrintStream을사용해서원하는형태로출력할수있다. - PrintStream은구버전으로가능하면 PrintWriter 클래스를사용한다. PrintWriter

Design Issues

학습목차 2.1 다차원배열이란 차원배열의주소와값의참조

쉽게 풀어쓴 C 프로그래밍

q 이장에서다룰내용 1 객체지향프로그래밍의이해 2 객체지향언어 : 자바 2

슬라이드 1

Secure Programming Lecture1 : Introduction

Microsoft PowerPoint - Chap12-OOP.ppt

쉽게 풀어쓴 C 프로그래밊

본 강의에 들어가기 전

1. What is AX1 AX1 Program은 WIZnet 사의 Hardwired TCP/IP Chip인 iinchip 들의성능평가및 Test를위해제작된 Windows 기반의 PC Program이다. AX1은 Internet을통해 iinchip Evaluation

슬라이드 1

쉽게 풀어쓴 C 프로그래밍

chap 5: Trees

슬라이드 1

Microsoft PowerPoint - [EEL2] Lab10.pptx

Microsoft PowerPoint - Chapter 6.ppt

JMF2_심빈구.PDF

API - Notification 메크로를통하여어느특정상황이되었을때 SolidWorks 및보낸경로를통하여알림메시지를보낼수있습니다. 이번기술자료에서는메크로에서이벤트처리기를통하여진행할예정이며, 메크로에서작업을수행하는데유용할것입니다. 알림이벤트핸들러는응용프로그램구현하는데있어

Microsoft PowerPoint - Supplement-02-Socket Overview.ppt [호환 모드]

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C D616E2E637070>

C++ Programming

C프로-3장c03逞풚

Microsoft PowerPoint - RMI.ppt

Cluster management software

Transcription:

프로그램설명 (TcpClient) 1 행 ~5 행.NET classes IOException Encoding IPAddress class Sockets 11 행 ~22 행 서버가클라이언트와같은컴퓨터에서실행되므로서버의주소는 Loopback(127.0.0.1) 으로지정 연결하려는서버의 port 번호 서버로송신할메시지 String 객체메시지는 Byte 배열로 Encoding 해야함 ( 한글이있으므로 Unicode) 18 행 : TCP socket 은일련의바이트 (sequences of bytes) 를주고받으므로 string 객체의문자열은 Byte 배열로전환되어야한다.

프로그램설명 (TcpClient) 11 행 ~22 행 클라이언트 Socket 객체생성함과동시에서버에연결 ( 생성자에서버의 IP 주소와 Port 번호를전달 ) 연결된 Socket 에서 NetworkStream 객체를얻음 ( 데이터송수신용 ) NeworkSteam 객체를사용하여서버에데이터전송 보낸메시지의길이만큼의 byte 를받을때까지 while 문안에서반복하여 Read. 만약받은데이터의길이가 0 인경우에는상대방과연결이끊어진것임. 송수신이성공했던실패했던마지막엔스트림과 Socket 을닫음. 31 행 : netstream.write(bytebuffer, 0, bytebuffer.length); 는 bytebuffer 에있는데이터를보내는데보내는데이터의시작위치는 0 번위치이고보내는양은길이 bytebuffer.length 만큼전송한다. ( 명령어는모든데이터를한번에보내는것처럼보이지만실제하부에서전달될때는작은덩어리로나누어서전달될수있다. 39 행 ~47 행 : 상대방이보내는데이터가한번에오지않을수있기때문에 while 문안에서원하는양의데이트를모두받을때까지반복하여수신한다. 만약기대하는만큼의데이터가도착하지않은상태에서 Read 함수가 0 을 return 하면그것은연결이비정상적으로종료된것으로생각할수있다.

TcpClient 클래스 TcpClient 는 TCP 프로토콜을사용하여쉽게상대방에연결하고데이터를주고받을수있는기능을제공하는클래스이다. 생성자 : public TcpClient(); public TcpClient(IPEndPoint localep); public TcpClient(string hostname, int port); TcpClient 생성자는위와같이세종류가있는데두번째생성자의경우는 IPEndPoint 에상대방의 IP 주소와 Port 번호정보가들어있다. 마지막생성자는호스트이름 /IP 주소, Port 번호가따로주어진다. 첫번째생성자처럼연결을위한정보가주어지지않은경우에는객체생성후사용하기전에반드기 Connect() 함수를호출하여직접연결을하여야한다. Methods: public void Close(); TCP 연결을종료한다. public void Connect(IPEndPoint); public void Connect(IPAddress address, int port); public void Connect(string hostname, int port); 위의생성자에서첫번째생성자를사용하여아직연결이되어있지않은경우에여기의세개의 Connect() 함수를사용하여연결을할수있다. ArgumentNullException, ArgumentOutOfRangeException, SocketException, ObjectDisposedException 등이발생할수있다. public NetworkStream GetStream(); NetworkStream 객체를 return 한다. InvalidOperationException, ObjectDisposedException

IPEndPoint 클래스 IPEndPoint 는 IP 주소와 Port 번호의쌍으로이루어진네트워크의종단의정보를갖고있다. 생성자 : public IPEndPoint(long address, int port); public IPEndPoint(IPAddress address, int port); 두개의생성자가있고각각망의종단점의정보를 argument 로받아들인다. Method: public virtual string ToString(); IPEndPoint 객체가가지고있는주소를문자열형태로 return 한다. 프로퍼티 : public IPAddress Address get; set; 종단점의 IP 주소를가지고있는 IPAddress 객체 public int Port get; set; 종단점의포트번호를가지고있는정수를가져오거나지정.

TcpListener 클래스 TcpListener 클라이언트의연결요청을관리하고요청을받아들이는등의기능을수행하는서버측 TCP 관리객체이다. 생성자 : public TcpListener(int port); public TcpListener(IPEndPoint localep); public TcpListener(IPAddress address, int port); 세개의생성자가있으나 port 번호만사용하는첫번째생성자는더이상사용되지않는다. Method: public Socket AcceptSocket(); 기다리고있는연결요청을받아서연결하고연결된 Socket 을 return. 이 Socket 을사용하여데이터를 send, receive 한다. public TcpClient AcceptClient(); 기다리고있는연결요청을받아서연결하고연결된 TcpClient 를 return. 이객체가제공하는 NetworkStream 을사용하여데이터를 read, write. public bool Pending(); 기다리고있는연결요청이있으면 true 를 return. Otherwise.. public void Start(); TcpListener 가내포하고있는 Socket 을초기화하고, Listen 을시작. public void Stop(); Listen 을종료하고 TcpListener 를닫는다. Accept 된 TcpClient 객체나, Socket 객체는개별적으로 close 해야함.

NetworkStream 클래스 Stream 은.NET 이제공하는추상화된기본적인 I/O 방식이다. Stream 은연속으로늘어선 Byte 들의흐름으로생각할수있다. 연결이완료된 TcpClient 객체는 NetworkStream 객체를가지고있어서이 Stream 객체를사용하여데이터를보내거나 (write), 가져온다 (read). Method: public virtual void Close(); NetworkStream 객체를닫는다. public abstract int Read(byte[] buffer, int offset, int len); len 만큼의 Byte 를읽어서 Buffer 의앞에서부터 offset 만큼떨어진위치에서부터 len 만큼의장소에집어넣는다. public abstract void Write(byte[] buffer, int offset, int len); buffer 의앞에서부터 offset 만큼떨어지위치에서부터시작해서길이 len 만큼의 byte 를전송한다. 프로퍼티 : public virtual bool DataAvailable get; Stream 에읽을데이터가있으면 true 를 return 한다.

.NET Socket 클래스 앞에서사용한 TcpListener, TcpClient 클래스들은 Socket객체를쉽게사용할수있도록제공되는 Wrapper 클래스이다. 이클래스들을사용하면코딩도간결하고쉽지만아무래도기능면에서는어느정도제한이있다. 따라서, 간단함프로그램이아니라면 Socket클래스의객체를직접사용해야할경우도있을것이다. 여기서는앞에서코딩했던 TcpEchoServer, TcpEchoClient를 Socket 객체를직접사용하는방법으로다시작성하였다. 다음의서버, 클라이언트프로그램의코드를복사하여실행해보라. TcpSocketServer using System; using System.Net; using System.Net.Sockets; namespace pjkim.tcpechoserversocket class TcpEchoServerSocket const int BUFSIZE = 100; // 데이터받는버퍼크기 const int BACKLOG = 5; // 연결요청을기다리는큐의길이 static void Main() int servport = 9999; Socket server = null; try server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); server.bind(new IPEndPoint(IPAddress.Any, servport)); server.listen(backlog); catch(socketexception e) Console.WriteLine(e.ErrorCode + ": " + e.message); Environment.Exit(e.ErrorCode); //catch byte[] rcvbuffer = new byte[bufsize]; int bytesrcvd; 다음페이지에계속

앞페이지의코드뒤에붙여넣으세요 for(;;) Socket client = null; try client = server.accept(); Console.WriteLine("0 의 Client 가연결되었습니다.", client.remoteendpoint); int totalbytesechoed = 0; while((bytesrcvd = client.receive(rcvbuffer, 0, rcvbuffer.length, SocketFlags.None)) > 0 ) client.send(rcvbuffer, 0, bytesrcvd, SocketFlags.None); totalbytesechoed += bytesrcvd; //while Console.WriteLine("0 바이트를받아서전송했습니다.", totalbytesechoed); client.close(); catch(exception e) Console.WriteLine(e.Message); if(client!= null) client.close(); //Main(); //class TcpEchoServerSocket //ns

TcpSocketClient using System; using System.Text; using System.IO; using System.Net.Sockets; using System.Net; namespace pjkim.tcpsocketclient class TcpSocketClient static void Main() string server = IPAddress.Loopback.ToString(); int servport = 9999; string msg = "TCP 소켓을직접사용하는 Echo 테스트 "; byte[] bytebuffer = Encoding.Unicode.GetBytes(msg); Socket sock = null; try sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint serverendpoint = new IPEndPoint(Dns.Resolve(server).AddressList[0], servport); sock.connect(serverendpoint); Console.WriteLine(" 서버에연결되었습니다. 메시지를보냅니다 "); sock.send(bytebuffer, 0, bytebuffer.length, SocketFlags.None); Console.WriteLine("0 바이트를전송했습니다.\n", bytebuffer.length); int totalbytesrcvd = 0; int bytesrcvd = 0; for (; totalbytesrcvd < bytebuffer.length; ) if ((bytesrcvd = sock.receive(bytebuffer, totalbytesrcvd, bytebuffer.length - totalbytesrcvd, SocketFlags.None)) == 0) Console.WriteLine(" 연결이예상치않게종료되었습니다."); break; totalbytesrcvd += bytesrcvd; //for Console.WriteLine(" 서버로부터총 0 바이트의메시지를받았습니다 : \n 메시지 : [1]\n", totalbytesrcvd, Encoding.Unicode.GetString(byteBuffer, 0, totalbytesrcvd)); catch(exception e) Console.WriteLine(e.Message); finally sock.close(); //class TcpSocketClient //ns

TcpSocketServer.cs 서버 Tcp Socket 생성 최대다섯개의연결요청을관리 로컬인터페이스에연결

데이터를받기위한버퍼선언 (100 바이트 ) 받은바이트수를저장하는정수변수 연결요청을받아들임 ( 연결된 Socket return) 데이터를받음 ( 받은바이트수 return) 전송한바이트수를누적 방금받은데이터를바로전송 Socket 을닫음. ( 연결끊기 )

TcpSocketClient.cs 서버와클라이언트가같은호스트에서실행되므로 Loopback 주소 127.0.0;1 을사용 Port 는 9999 를사용 전송할메시지를 Unicode 로엔코딩하여 Byte 배열에저장 서버의주로와 Port 번호로 EndPoint 를만든후 Connect 함수로연결요청 소켓생성 데이터전송 서버로부터데이터받음. 서버는클라이언트로부터받은데이터를바로전송 서버로부터받은바이트를 String 으로 Encoding 하여출력 Socket 을닫고연결을끊음.

UDP 소켓 UDP 소켓은 TCP 와는다른방법의전송서비스를제공한다. UDP 소켓은데이터를주고받는상대방과미리연결을설정하지않는다. TCP 소켓이전화에비교된다면, UDP 소켓은편지를주고받는것에비유할수있다. 전화는상대방과연결이되고내가누구와통화중이라는사실을알고있게된다. 반면에편지는누구에게서어떤편지가언제올것인지미리통보하지않은상태에서받게된다. 편지를받고답장을하려면편지봉투에적힌보낸사람의주소를사용하여보낸다. 전화는통화중인경우에는다른사람과의통화를동시에할수없지만편지는편지통에여러명으로부터의편지가도착할수있고각각에대한답장도개별적으로한다. UDP 의장점 : 높은효율성 : 연결등에부가되는작업이없기때문에작은양의데이터를보내는데는 TCP 보다효율적이다. 유연성 : 신뢰성이강조되는작업이아니라면 UDP 는그어떤용도로사용되더라도오버헤드를최소화할수있다. UDP 의단점 : 낮은신뢰성 : 데이터가응용프로그램에도착하지않고사라질수있다. 또한, 응용프로그램에도착한데이터의순서가바뀌어있을수있다. TCP 의경우에는 TCP 가이런경우에대한대처를하지만 UDP 를사용하는경우에는응용프로그램이자체적으로에러데대한처리를하여야한다.

UDP 소켓을사용하는클라이언트 프로젝트를만들고다음의코드를복사하여실행하라. ( 클라이언트, 서버프로젝트를모두완성한후테스트 ) UdpEchoClient.cs using System; using System.Text; using System.Net; using System.Net.Sockets; namespace cn.udpechoclient class UdpEchoClient static void Main() string server = IPAddress.Loopback.ToString(); int portno = 8888; byte[] bytebuffer = Encoding.Unicode.GetBytes(" 컴퓨터학과소켓프로그래밍 "); UdpClient client = new UdpClient(); try client.send(bytebuffer, bytebuffer.length, server, portno); Console.WriteLine("0 바이트를서버로보냄 ", bytebuffer.length); IPEndPoint remoteipendpoint = new IPEndPoint(IPAddress.Any, 0); byte[] rcvbuffer = client.receive(ref remoteipendpoint); Console.WriteLine("0 바이트를 1 로부터받았습니다. msg: [2]", rcvbuffer.length, remoteipendpoint, Encoding.Unicode.GetString(rcvBuffer, 0, rcvbuffer.length)); catch(socketexception e) Console.WriteLine(e.ErrorCode + ": " + e.message); client.close(); //Main() //class UdpEchoClient //ns

UDP 소켓을사용하는서버 UdpEchoServer.cs using System; using System.Net; using System.Net.Sockets; namespace cn.udpechoserve class UdpEchoServe static void Main() UdpClient client = null; try client = new UdpClient(8888); catch (SocketException e) Console.WriteLine(e.ErrorCode + ": " + e.message); Environment.Exit(e.ErrorCode); IPEndPoint remoteipendpoint = new IPEndPoint(IPAddress.Any, 0); for(;;) try byte[] bytebuffer = client.receive(ref remoteipendpoint); Console.Write(" 클라이언트 0 를처리하고있습니다...", remoteipendpoint); client.send(bytebuffer, bytebuffer.length, remoteipendpoint); Console.WriteLine("0 바이트를전송했습니다.", bytebuffer.length); catch(socketexception e) Console.WriteLine(e.ErrorCode + ": " + e.message); //for(;;) //Main() //CLASS UdpEchoServe //ns

UdpEchoClient.cs 설명 메시지를보낼서버의주소지정 메시지를보낼서버의포트번호 전송할메시지 (bytes) UDP 소켓생성 연결없이바로서버로메시지전송 상대방의주소를받을객체생성 소켓닫기 상대방의메시지를기다렸다가받음. 메시지는함수가 return, 상대방의주소는 IPEndPoint 객체파라메터로받음

UdpEchoServer.cs 설명 클라이언트와메시지를주소받을 UdpClient 객체선언 Udp 서버는클라이언트를받아들이고연결을수락하는등의일을하지않고마치클라이언트처럼 UdpClient 소켓하나로상대방으로부터의메시지를기다린다. 따라서포트번호를지정하는것이외에는클라이언트와구조가크게다르지않다. 도착한메시지의상대방주소를얻기위한객체선언 도착한메시지와상대방주소를얻음 받은메시지를상대방주소로전송 ( 에코 )

클라이언트와서버의응용프로그램레벨에서주소받는데이터는서로같은의미로해석되어야한다. 따라서응용프로그램간에는주고받는데이터의포맷을공유하여야한다. C# 에서는전송하는데이터도대부분 class 의객체내부에존재한다. 실제객체의데이터는다른장소에있고객체의참조는주소만가지고있기때문에객체내부에있는데이터가메모리상에연속적으로있다는보장도없다. 따라서, 전송자가객체를직접전송하고수신자가같은타입의객체를받는다해도받은것은상대방컴퓨터내부의주소일뿐수신자내부에서는아무의미가없다. 따라서, C# 에서는클라이언트와서버간에모든데이터전송은 8bit(byte) 덩어리의연속으로바꾸어서전송하여야한다. 따라서, C# 에서는송수신자간에데이터를주고받기위해서는객체의데이터를 byte 배열로바꾸는 Encoding 기능과 byte 배열을다시같은타입의동일한 class 의객체로바꾸어주는 Decoding 기능을구현하여서송수신자간에공유하여야한다. Encoding 과 Decoding 의기능을구현하는데는두가지방법이있다. 첫번째는 Encoding 에의하여객체의데이터를 Byte 배열로만들때배열내에서데이터와데이터사이를구별할수있는구분자를삽입하는방법이다. 이방법에서구분자는데이터상에서나타날수없는값을사용하여야한다 ( 예 : \n );. Decoding 기능은 byte 배열에섞여있는구분자를사용하여데이터를추출하고이추출된개별적인데이터를사용하여본래의객체를다시생성하여야한다. 또다른하나의방법으로는데이터를보내기전에미리전송될데이터의길이를알려주는방법이있다. 이방법을사용하는데있어서미리고정된길이의데이터인경우에는송수신자간에이미데이터의길이가고정되어있기때문에특별히데이터의길이를보내줄필요가없다. 그러나문자열과같이가변길이의데이터의앞에는먼저길이를나타내는고정길이형의데이터 ( 정수형 ) 를붙여서뒤에있는 데이터의바이트수를알려주어야한다. Encoder 나 Decoder 가같은규칙을사용함으로써서로의미있는데이터 ( 객체 ) 를주고받을수있게된다. 다음의코드는이를설명하기위한몇몇파일의코드이다.

견적서.cs using System; using System.IO; using System.Text; using System.Net; //-- 견적서 class ------------------------------ public class 견적서 public long itemnumber; public string itemdescription; public int quantity; public int unitprice; public bool discounted; public bool instock; public 견적서 (long itemnumber, string itemdescription, int quantity, int unitprice, bool discounted, bool instock) this.itemnumber = itemnumber; this.itemdescription = itemdescription; this.quantity = quantity; this.unitprice = unitprice; this.discounted = discounted; this.instock = instock; public override string ToString() //return base.tostring(); string str = " 상품코드 = " + itemnumber + "\n" + " 상품명 = " + itemdescription + "\n" + " 수량 = " + quantity + "\n" + " 단가 = " + unitprice; if (discounted) str += " ( 할인가 )"; if (instock) str += "\n 재고있음 "; else str += "\n 재고없음 "; return str; //class 견적서 계속

//--------------------------------------------------------- public class 견적서 TextConst public static readonly string DEFAULT_CHAR_ENC = "ascii"; public static readonly int MAX_WIRE_LENGTH = 1024; //class MessageConst //------------------------------------------------------- public interface 견적서 Encoder byte[] encode( 견적서 item); //interface MessageEncoder //------------------------------------------------------- public interface 견적서 Decoder 견적서 decode(stream source); 견적서 decode(byte[] packet); //interface MessageDecoder //---------------------------------------------- class 견적서 EncoderText : 견적서 Encoder public Encoding encoding; public 견적서 EncoderText() : this( 견적서 TextConst.DEFAULT_CHAR_ENC) public 견적서 EncoderText(string encodingdesc) encoding = Encoding.GetEncoding(encodingDesc); public byte[] encode( 견적서 item) string encodedstring = ""; encodedstring += item.itemnumber + " "; if(item.itemdescription.indexof('\n')!= -1) throw new IOException(" 문자열에이미 nextline 문자가있습니다."); encodedstring += item.itemdescription + "\n"; encodedstring += item.quantity + " "; encodedstring += item.unitprice + " "; if (item.discounted) encodedstring += "d"; if (item.instock) encodedstring += "s"; encodedstring += "\n"; if (encodedstring.length > 견적서 TextConst.MAX_WIRE_LENGTH) throw new IOException("Encoding 된메시지길이가최대값을초과했습니다."); byte[] buf = encoding.getbytes(encodedstring); return buf; //encode( 견적서 item) //class 견적서 EncoderText 계속

//-------------------------------------------------------- public class 견적서 DecoderText : 견적서 Decoder public Encoding encoding; public 견적서 DecoderText() : this( 견적서 TextConst.DEFAULT_CHAR_ENC) public 견적서 DecoderText(string encodingdesc) encoding = Encoding.GetEncoding(encodingDesc); //------- public 견적서 decode(stream wire) string itemno, description, quant, price, flags; byte[] space = encoding.getbytes(" "); byte[] newline = encoding.getbytes("\n"); itemno = encoding.getstring(framer.nexttoken(wire, space)); description = encoding.getstring(framer.nexttoken(wire, newline)); quant = encoding.getstring(framer.nexttoken(wire, space)); price = encoding.getstring(framer.nexttoken(wire, space)); flags = encoding.getstring(framer.nexttoken(wire, newline)); return new 견적서 (Int64.Parse(itemNo), description, Int32.Parse(quant), Int32.Parse(price), (flags.indexof('d')!= -1), (flags.indexof('s')!= -1)); //----- public 견적서 decode(byte[] packet) Stream memstream = new MemoryStream(packet, 0, packet.length, false); return decode(memstream); //class 견적서DecoderText //-------------------------------------------------------------- 계속

public class 견적서 BinConst public static readonly string DEFAULT_CHAR_ENC = "ascii"; public static readonly byte DISCOUNT_FLAG = 1 << 7; public static readonly byte IN_STOCK_FLAG = 1 << 0; public static readonly int MAX_DESC_LEN = 255; public static readonly int MAX_WIRE_LENGTH = 1024; //--------------------------------------------------------------- public class 견적서 EncoderBin : 견적서 Encoder public Encoding encoding; public 견적서 EncoderBin() : this( 견적서 BinConst.DEFAULT_CHAR_ENC) public 견적서 EncoderBin(string encodingdesc) encoding = Encoding.GetEncoding(encodingDesc); public byte[] encode( 견적서 item) MemoryStream mem = new MemoryStream(); BinaryWriter output = new BinaryWriter(new BufferedStream(mem)); output.write(ipaddress.hosttonetworkorder(item.itemnumber)); output.write(ipaddress.hosttonetworkorder(item.quantity)); output.write(ipaddress.hosttonetworkorder(item.unitprice)); byte flags = 0; if (item.discounted) flags = 견적서 BinConst.DISCOUNT_FLAG; if (item.instock) flags = 견적서 BinConst.IN_STOCK_FLAG; output.write(flags); byte[] encodeddesc = encoding.getbytes(item.itemdescription); if(encodeddesc.length > 견적서 BinConst.MAX_DESC_LEN) throw new IOException(" 견적서의상품명이 encoding 최대길이를초과합니다."); output.write((byte)encodeddesc.length); output.write(encodeddesc); output.flush(); return mem.toarray(); //class 견적서EncoderBin 계속

//------------------------------------------- public class 견적서 DecoderBin : 견적서 Decoder public Encoding encoding; // 생성자 public 견적서 DecoderBin() : this( 견적서 BinConst.DEFAULT_CHAR_ENC) public 견적서 DecoderBin(string encodingdesc) encoding = Encoding.GetEncoding(encodingDesc); //---------------- public 견적서 decode(stream wire) BinaryReader src = new BinaryReader(new BufferedStream(wire)); long itemnumber = IPAddress.NetworkToHostOrder(src.ReadInt64()); int quantity = IPAddress.NetworkToHostOrder(src.ReadInt32()); int unitprice = IPAddress.NetworkToHostOrder(src.ReadInt32()); byte flags = src.readbyte(); int stringlength = src.read(); if(stringlength == -1) throw new EndOfStreamException(); byte[] stringbuf = new byte[stringlength]; src.read(stringbuf, 0, stringlength); string itemdesc = encoding.getstring(stringbuf); return new 견적서 (itemnumber, itemdesc, quantity, unitprice, ((flags & 견적서 BinConst.DISCOUNT_FLAG)!= 0), ((flags & 견적서 BinConst.IN_STOCK_FLAG)!= 0)); //decode() //--------------------- public 견적서 decode(byte[] packet) Stream memstream = new MemoryStream(packet, 0, packet.length, false); return decode(memstream); //class 견적서DecoderBin 견적서.cs 끝

Framer.cs using System; using System.IO; //----------------------------------------------------- public class Framer public static byte[] nexttoken(stream input, byte[] delimiter) int nextbyte; if((nextbyte = input.readbyte()) == -1) return null; MemoryStream tokenbuffer = new MemoryStream(); do tokenbuffer.writebyte((byte)nextbyte); byte[] currenttoken = tokenbuffer.toarray(); if(endswith(currenttoken, delimiter)) int tokenlength = currenttoken.length - delimiter.length; byte[] token = new byte[tokenlength]; Array.Copy(currentToken, 0, token, 0, tokenlength); return token; //if while ((nextbyte = input.readbyte())!= -1); return tokenbuffer.toarray(); //static nexttoken //--------------------------------------------------------- private static bool endswith(byte[] value, byte[] delimiter) if(value.length < delimiter.length) return false; for(int i=1; i<=delimiter.length; i++) if(value[value.length - i]!= delimiter[delimiter.length - i]) return false; //for return true; //static bool endswith //class Framer Framer.cs 끝 위에서제공한두개의파일의코드를사용하여클라이언트과서버가견적서객체를주고받아서처리하는 TCP 소켓프로그램을작성하여보라.