노력과 삽질 퇴적물
C#: 문법 스캔 (3) 본문
|
|
목차
|
|
(1)
|
이론 |
(2)
|
TCP |
(3)
|
소켓 |
* 주요 참조자료상, 닷넷 기반 TCP/IP, UDP입니다.
1. 이론
1) TCP
> TCP클라이언트와 TCP Listener 클래스가 사용된.
2) UDP
> 연결지향인 TCP와 달리, UDP는 속도를 중시한 처리가 중요한 프로토콜.
* TCP클라이언트/Listener 클래스와 UDP클라이언트 클래스는 내부적으로 소켓 클래스 사용하고, 소켓 클래스는 low-level 소켓 프로그래밍 지원.
* 해당 포스팅에서는 UDP 예시는 생략.
* TCP클라이언트/Listener 클래스와 UDP클라이언트 클래스는 내부적으로 소켓 클래스 사용하고, 소켓 클래스는 low-level 소켓 프로그래밍 지원.
* 해당 포스팅에서는 UDP 예시는 생략.
2. TCP
1) 클라이언트 사이드
> 인코딩/디코딩 절차상, 예제의 문자열뿐 아니라 이미지같은 미디어 전송도 가능.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
using System;
using System.Net.Sockets;
... ... ...
//STEP.1 IP주소와 포트번호
TcpClient tClient = new TcpClient("127.0.0.1", 80);
string requestMsg = "2021_05_17";
byte[] encodedBytes = Encoding.ASCII.GetBytes(requestMsg);//인코딩처리.
//STEP.2 NetworkStream
NetworkStream nwStream = tClient.GetStream();
//STEP.3 NetworkStream.Write
nwStream.Write(encodedBytes, 0, encodedBytes.Length);
//STEP.4 NetworkStream.Read
byte[] recivedBytes = new byte[1024];
int nbytes = nwStream.Read(recivedBytes, 0, recivedBytes.Length);
string resultMsg = Encoding.ASCII.GetString(recivedBytes, 0, nbytes);
//STEP.5 접속종료
nwStream.Close();
tClient.Close();
|
cs |
(HTTP 프로토콜처럼)연결 끊길때까지 처리하려면 STEP.4에서
1
2
3
4
5
6
7
8
9
|
byte[] recivedBytes = new byte[1024];
int nbytes;
MemoryStream mStream = new MemoryStream();
while ((nbytes = nwStream.Read(recivedBytes, 0, recivedBytes.Length)) > 0)
{
mStream.Write(recivedBytes, 0, nbytes);
}
byte[] resultBytes = mStream.ToArray();
mStream.Close();
|
cs |
MemoryStream으로 루프 돌려야.
2) TCP Listener를 이용한 비동기 서버
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
static void Main(string[] args)
{
TestTcpAysnc().Wait();
}
... ... ...
async static Task TestTcpAysnc()
{
int port = 2021;
IPAddress targetAddress = IPAddress.Parse("127.0.0.1");
TcpListener tListener = new TcpListener(targetAddress, port);
try
{
tListener.Start();
} catch(SocketException e) {
//do-something.
} finally {
tListener.Stop();
}
while (true)
{
TcpClient tcpClient = await tListener.AcceptTcpClientAsync().ConfigureAwait(false);
Task.Factory.StartNew(doStreamAsync, tcpClient);//to new thread
}
}
async static void doStreamAsync(object argObj)
{
TcpClient tcpClient = (TcpClient)argObj;
NetworkStream nwStream = tcpClient.GetStream();
String msg = null;
byte[] buff = new byte[1024];//512, 1024, 2048 ...
var nBytes = await nwStream.ReadAsync(buff, 0, buff.Length).ConfigureAwait(false);
if (nBytes > 0)
{
msg = Encoding.ASCII.GetString(buff, 0, nbytes);
await nwStream.WriteAsync(buff, 0, nbytes).ConfigureAwait(false);
}
nwStream.Close();
tcpClient.Close();
}
|
cs |
3. 소켓
1) 클라이언트 사이드
> Connect->Send->Receive->Close
2) 서버 사이드
> (Bind->Listen->Accept)->(Receive->Send)->Close
// 서버가 블라블라(BLA BLA)하는걸 듣고서 대답하고 닫기.
3) 비동기 소켓 서버
1) 한국어
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
using System.Net;
using System.Net.Sockets;
... ... ...
public class TestSocket
{
public static void Main(string[] args)
{
int port = 8080;
Socket socket = null;
byte[] requestBytes = Encoding.ASCII.GetBytes( string.Empty );
byte[] responseBytes = new byte[8192];
//STEP.1 연결관련 객체
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("172.0.0.1"), port);
socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
//STEP.2 서버에 연결
socket.Connect(endPoint);
while ((cmd = Console.ReadLine()) != "q")
{
requestBytes = Encoding.UTF8.GetBytes(cmd);
try{
//STEP.3 리퀘스트
socket.Send(requestBytes, requestBytes.Length, 0);
//STEP.4 리스폰스
int responseInt = socket.Receive(responseBytes, responseBytes.Length, 0);
string response = Encoding.UTF8.GetString(responseBytes, 0, responseInt);
Console.WriteLine(response);
} catch(SocketException except){
Console.WriteLine(except.ErrorCode);
//do-something
}
}
//STEP.5
socket.Close();
}
}
|
cs |
2) 서버 사이드
> (Bind->Listen->Accept)->(Receive->Send)->Close
// 서버가 블라블라(BLA BLA)하는걸 듣고서 대답하고 닫기.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
using System.Net;
using System.Net.Sockets;
... ... ...
namespace TestSocketServer
{
static void Main(string[] args)
{
int port = 8080;
Socket serverSocket = null;
Socket clientSocket = null;
byte[] responseBytes = new byte[8192];
//STEP.1 소켓 객체
IPEndPoint endPoint = new IPEndPoint("172.0.0.1", port);
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try{
//STEP.2 (포트번호대로)수신 시작.
serverSocket.Bind(endPoint);
serverSocket.Listen(10);
//STEP.3 새소켓
clientSocket = serverSocket.Accept();
} catch(SocketException except){
Console.WriteLine(except.ErrorCode);
} catch(ObjectDisposedException except){
Console.WriteLine(except.ErrorCode);
}
int responseResult = -1;
string responseString = null;
while (!Console.KeyAvailable)
{
//STEP.4 새소켓으로 수신
responseResult = clientSocket.Receive(responseBytes);
responseString = Encoding.UTF8.GetString(responseBytes, 0, responseResult);
//STEP.5 답신
clientSocket.Send(responseBytes, 0, receiveResult, SocketFlags.None);
}
//STEP.6 소켓
clientSocket.Close();
socket.Close();
}
}
|
cs |
3) 비동기 소켓 서버
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
using System.Net;
using System.Net.Sockets;
using System.Threading;
... ... ...
namespace TestSocketServer
{
public static ManualResetEvent _threadEvent = new ManualResetEvent(false);
static void Main(string[] args)
{
int port = 8080;
Socket serverSocket = null;
//STEP.1 소켓 객체
IPEndPoint endPoint = new IPEndPoint("172.0.0.1", port);
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try{
//STEP.2 (포트번호대로)수신 시작.
serverSocket.Bind(endPoint);
serverSocket.Listen(10);
} catch(SocketException except){
Console.WriteLine(except.ErrorCode);
} catch(ObjectDisposedException except){
Console.WriteLine(except.ErrorCode);
}
try{
while (true)
{
_threadEvent.Reset();
//STEP.3 클라이언트 요청이 있을때마다 요청 수락
serverSocket.BeginAccept(SocketCallback, serverSocket);//Accept.시작
_threadEvent.WaitOne();// Wait until a connection is made before continuing.
}
} catch(Exception except){
Console.WriteLine(except.ErrorCode);
}
}
private static void SocketCallback(IAsyncResult argResultAsync)
{
Console.WriteLine("Accepted");
Console.ReadLine();
_threadEvent.Set();// Signal the main thread to continue.
Socket listener = (Socket)argResultAsync.AsyncState;
Socket clientSocket = listener.EndAccept(argResultAsync);//Accept.끝
clientSocket.Close();
}
}
|
cs |
기타. 참조자료
1) 한국어
> UDP 서버
> Socket 클라이언트
> Socket 서버
> 비동기 Socket 서버
> .NET Framework: 921. C# - I/O 스레드를 사용한 비동기 소켓 서버/클라이언트
MSDN
> Socket 서버
> 비동기 Socket 서버
> .NET Framework: 921. C# - I/O 스레드를 사용한 비동기 소켓 서버/클라이언트
MSDN
> TcpListener 클래스 (System.Net.Sockets) | Microsoft Docs
> Socket 클래스 (System.Net.Sockets) | Microsoft Docs
> 비동기 서버 소켓 예제 | Microsoft Docs
> Socket 클래스 (System.Net.Sockets) | Microsoft Docs
> 비동기 서버 소켓 예제 | Microsoft Docs
기타. 변경이력
일자
|
변경이력 |
2021-07-15 | 초안 작성. [#blogger] |
'📂기초 및 세팅 note > 언어. C# 계열' 카테고리의 다른 글
C#: 문법 스캔 (2) (0) | 2021.07.16 |
---|---|
C#: 문법 스캔 (1) (0) | 2021.03.01 |
이론: 닷넷 프레임워크(.NET Framework) (0) | 2016.08.21 |
C#: 기초문법 (0) | 2015.12.21 |