-
-
Save jacking75/8fa083cf407a41d7d268c971bce519dc to your computer and use it in GitHub Desktop.
.NETでTCP(TcpClientとTcpListener)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Net; | |
using System.Net.Sockets; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Tcp.ConsoleApp { | |
// 클라이언트 | |
public class Client<TRequest, TResponse> { | |
// 접속처의 엔드포인트 | |
private readonly IPEndPoint _endpoint; | |
public Client(IPEndPoint endpoint) { | |
_endpoint = endpoint; | |
} | |
// 서버에 요청을 보내고 답변을 받는다 | |
public async Task<TResponse> Send(TRequest request) { | |
using (var client = new TcpClient()) { | |
// 1. 서버에 접속 | |
await client.ConnectAsync(_endpoint.Address, _endpoint.Port); | |
using (var stream = client.GetStream()) { | |
// 2. 서버에 요청을 보낸다 | |
Console.WriteLine($"Client send: {request}"); | |
stream.WriteObject(request); | |
// 3. 서버에서 답변을 수신한다 | |
var response = stream.ReadObject<TResponse>(); | |
Console.WriteLine($"Client received: {response}"); | |
return response; | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Tcp.ConsoleApp { | |
// 메시지 | |
[Serializable] | |
public class Message { | |
public int Id { get; set; } | |
public string Content { get; set; } | |
public override string ToString() { | |
return $@"{{ {nameof(Id)} = {Id}, {nameof(Content)} = ""{Content}"" }}"; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Runtime.Serialization; | |
using System.Runtime.Serialization.Formatters.Binary; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Tcp.ConsoleApp { | |
// 오브젝트와 바이트 배열의 변환 | |
public class ObjectConverter<TObject> { | |
private readonly IFormatter _formatter; | |
public ObjectConverter(IFormatter formatter = null) { | |
_formatter = formatter ?? new BinaryFormatter(); | |
} | |
// 오브젝트=>바이트 배열 | |
public byte[] ToByteArray(TObject obj) { | |
using (var stream = new MemoryStream()) { | |
_formatter.Serialize(stream, obj); | |
return stream.ToArray(); | |
} | |
} | |
// 바이트 배열=>오브젝트 | |
public TObject FromByteArray(byte[] bytes) { | |
using (var stream = new MemoryStream(bytes)) { | |
return (TObject)_formatter.Deserialize(stream); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Net; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Tcp.ConsoleApp { | |
class Program { | |
static void Main(string[] args) { | |
// 서버가 접속을 기다리는 엔드포인트이다 | |
// 클라이언트가 접속하는 서버의 엔드포인트 | |
var endpoint = new IPEndPoint(IPAddress.Loopback, 54321); | |
// 서버 | |
var server = new Server<Message, Message>( | |
endpoint, | |
// 요청에서 답변을 만드는 처리 | |
request => new Message { | |
Id = request.Id, | |
// 메시지의 문자열을 역순한다 | |
Content = new string(request.Content.Reverse().ToArray()), | |
}); | |
// 접속을 기다린다 | |
var task = Task.Run(() => server.Listen()); | |
// 클라이언트 | |
Task.WaitAll( | |
// 요청을 보내고 답변을 받는다 | |
new Client<Message, Message>(endpoint).Send(new Message { Id = 10, Content = "ABCDE" }), | |
new Client<Message, Message>(endpoint).Send(new Message { Id = 20, Content = "12345" }), | |
new Client<Message, Message>(endpoint).Send(new Message { Id = 30, Content = "가나다라마" }) | |
); | |
// 서버를 종료 | |
server.Close(); | |
// 서버의 종료 처리, Task 관리, 에러 처리 관련이 미묘 | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Net; | |
using System.Net.Sockets; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Tcp.ConsoleApp { | |
// 서버 | |
public class Server<TRequest, TResponse> { | |
// 접속을 대기하는 엔드포인트 | |
private readonly IPEndPoint _endpoint; | |
// 요청에서 답변을 만드는 처리 | |
private readonly Func<TRequest, TResponse> _processor; | |
// TCP 리스너 | |
private readonly TcpListener _listener; | |
public Server(IPEndPoint endpoint, Func<TRequest, TResponse> processor) { | |
_endpoint = endpoint; | |
_processor = processor; | |
_listener = new TcpListener(_endpoint); | |
} | |
// 클라이언트에서 요청을 수신하고 답변을 보낸다 | |
private void Receive(TcpClient client) { | |
using (client) | |
using (var stream = client.GetStream()) { | |
// 3. 클라이언트에서 요청을 수신한다 | |
var request = stream.ReadObject<TRequest>(); | |
// 4. 요청을 처리하고 답변을 만든다 | |
var response = _processor(request); | |
// 5. 클라이언트에 답변을 보낸다 | |
stream.WriteObject(response); | |
} | |
} | |
// 접속을 대기 | |
public async Task Listen() { | |
Console.WriteLine($"Server listen:"); | |
// 1. 클라이언트의 접속을 대기 | |
_listener.Start(); | |
while (true) { | |
// 2. 클라이언트로부터의 접속을 받아들인다. | |
var client = await _listener.AcceptTcpClientAsync(); | |
Console.WriteLine($"Server accepted:"); | |
var task = Task.Run(() => Receive(client)); | |
// Task 관리나 에러 처리는 생략 | |
} | |
} | |
// 종료한다 | |
public void Close() { | |
_listener.Stop(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Tcp.ConsoleApp { | |
public static class StreamExtensions { | |
// 오브젝트 로딩 | |
public static TObject ReadObject<TObject>(this Stream stream) { | |
using (var reader = new BinaryReader(stream, Encoding.UTF8, true)) { | |
// 길이를 읽고 바이트 배열을 읽는다 | |
var length = reader.ReadInt32(); | |
var bytes = reader.ReadBytes(length); | |
var converter = new ObjectConverter<TObject>(); | |
reProgramturn converter.FromByteArray(bytes); | |
} | |
} | |
// 오브젝트 쓰기 | |
public static void WriteObject<TObject>(this Stream stream, TObject obj) { | |
using (var writer = new BinaryWriter(stream, Encoding.UTF8, true)) { | |
var converter = new ObjectConverter<TObject>(); | |
var bytes = converter.ToByteArray(obj); | |
// 길이를 쓰고 바이트 배열을 쓴다 | |
writer.Write(bytes.Length); | |
writer.Write(bytes); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment