... | ... | @@ -1957,3 +1957,147 @@ static void ClientFunc() |
|
|
}
|
|
|
```
|
|
|
|
|
|
TCP 멀티 스레드 예제
|
|
|
|
|
|
```c#
|
|
|
class TCPSocketEx2 //TCP 다중 스레드
|
|
|
{
|
|
|
public static void Main()
|
|
|
{
|
|
|
//서버 소켓 스레드
|
|
|
Thread serverThread = new Thread(ServerFunc);
|
|
|
serverThread.IsBackground = true;
|
|
|
serverThread.Start();
|
|
|
|
|
|
Thread.Sleep(1000);
|
|
|
|
|
|
//클라이언트 소켓이 동작하는 스레드
|
|
|
Thread clientThread = new Thread(ClientFunc);
|
|
|
clientThread.IsBackground = true;
|
|
|
serverThread.Start();
|
|
|
|
|
|
Console.WriteLine("종료하려면 아무 키나 누르세요...");
|
|
|
Console.ReadLine();
|
|
|
}
|
|
|
|
|
|
static void ServerFunc()
|
|
|
{
|
|
|
using (Socket srvSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
|
|
{
|
|
|
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 11200);
|
|
|
|
|
|
srvSocket.Bind(endPoint);
|
|
|
|
|
|
srvSocket.Listen(10);
|
|
|
|
|
|
while(true)
|
|
|
{
|
|
|
Socket cliSocket = srvSocket.Accept(); //Accept받은 소켓을 스레드풀의 처리를 스레드 풀의 스레드에게 맡긴다.
|
|
|
ThreadPool.QueueUserWorkItem((WaitCallback)clientSocketProcess, cliSocket);
|
|
|
//하지만 한 클라이언트 당 하나의 스레드가 생성되면서 동시 처리할 수 있는 클라이언트 개수에 제한이 생긴다.
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private static void clientSocketProcess(object state)
|
|
|
{
|
|
|
Socket cliSocket = state as Socket;
|
|
|
|
|
|
byte[] recvBytes = new byte[1024];
|
|
|
|
|
|
int nRecv = cliSocket.Receive(recvBytes);
|
|
|
string txt = Encoding.UTF8.GetString(recvBytes, 0, nRecv);
|
|
|
|
|
|
byte[] sendBytes = Encoding.UTF8.GetBytes("Hello: " + txt);
|
|
|
cliSocket.Send(sendBytes);
|
|
|
cliSocket.Close();
|
|
|
}
|
|
|
|
|
|
static void ClientFunc()
|
|
|
{
|
|
|
//구현
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
TCP 비동기 통신 예제
|
|
|
|
|
|
```c#
|
|
|
public class AsyncStateData
|
|
|
{
|
|
|
public byte[] buffer;
|
|
|
public Socket socket;
|
|
|
}
|
|
|
|
|
|
class TCPSocketEx3 //TCP 비동기 통신 서버 예제
|
|
|
{
|
|
|
public static void Main()
|
|
|
{
|
|
|
//서버 소켓 스레드
|
|
|
Thread serverThread = new Thread(ServerFunc);
|
|
|
serverThread.IsBackground = true;
|
|
|
serverThread.Start();
|
|
|
|
|
|
Thread.Sleep(1000);
|
|
|
|
|
|
//클라이언트 소켓이 동작하는 스레드
|
|
|
Thread clientThread = new Thread(ClientFunc);
|
|
|
clientThread.IsBackground = true;
|
|
|
serverThread.Start();
|
|
|
|
|
|
Console.ReadLine();
|
|
|
}
|
|
|
|
|
|
static void ServerFunc()
|
|
|
{
|
|
|
using (Socket srvSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
|
|
{
|
|
|
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 11200);
|
|
|
|
|
|
srvSocket.Bind(endPoint);
|
|
|
|
|
|
srvSocket.Listen(10);
|
|
|
|
|
|
while(true)
|
|
|
{
|
|
|
Socket cliSocket = srvSocket.Accept();
|
|
|
|
|
|
AsyncStateData data = new AsyncStateData();
|
|
|
data.buffer = new byte[1024];
|
|
|
data.socket = cliSocket;
|
|
|
|
|
|
cliSocket.BeginReceive(data.buffer, 0, data.buffer.Length, SocketFlags.None, asyncReceiveCallback, data);
|
|
|
//비동기 동작
|
|
|
//바로 While문의 시작으로 돌아가 다른 클라이언트와의 연결을 지연없이 받을 수 있다.
|
|
|
//BeginRecv -> EndRecv -> BeginSend -> EndSend 순서대로 진행된다.
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private static void asyncReceiveCallback(IAsyncResult ar) //BeginReceive에서 콜백
|
|
|
{
|
|
|
AsyncStateData rcvData = ar.AsyncState as AsyncStateData;
|
|
|
|
|
|
int nRecv = rcvData.socket.EndReceive(ar);
|
|
|
string txt = Encoding.UTF8.GetString(rcvData.buffer, 0, nRecv); //문자열 데이터를 받는다.
|
|
|
|
|
|
byte[] sendBytes = Encoding.UTF8.GetBytes("Hello: " + txt); //받은 문자열에 Hello를 붙여서 다시 보낸다.
|
|
|
rcvData.socket.BeginSend(sendBytes, 0, sendBytes.Length, SocketFlags.None, asyncSendCallback, rcvData.socket);
|
|
|
}
|
|
|
|
|
|
private static void asyncSendCallback(IAsyncResult ar) //BeginSend에서 콜백
|
|
|
{
|
|
|
Socket socket = ar.AsyncState as Socket;
|
|
|
socket.EndSend(ar); //비동기 보내기 작업을 끝내준다.
|
|
|
|
|
|
socket.Close(); //소켓을 다 사용했으므로 닫아준다.
|
|
|
}
|
|
|
|
|
|
static void ClientFunc()
|
|
|
{
|
|
|
//구현
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
|