-
C# 소켓 Socket SocketAsyncEventArgs를 사용하여 채팅 프로그램 만들기 1C# 2025. 3. 5. 22:25
# 서론
취업를 위해 여기저기 공고를 넣으며 막연히 게임 서버 강의를 듣고 있던 나는 프로그램을 만들어 보지 않으면 강의 나 책 주구장창 봐도 의미가 없다는 소리를 듣고 채팅 서버 정도는 가볍게 만들지 않을까 생각하고 만들기를 시작했는데..
평소 공부한답시고 강의만 보고 코드를 작성 안했더니 생각보다 매끄럽게 코드 작성이 안되는 것을 깨달았다. 그래서 이번 소켓를 이용한 채팅 서버 작성을 통해 감을 되찾고 코드 작성 습관화를 목표로 진행할 예정이다.
# 채팅 프로그램 사양
클라이언트에서는 닉네임을 입력하여 채팅 서버에 접속하고 채팅 서버는 브로드캐스팅을 통해 입장한 모든 클라이언트에게 채팅를 보낼 수 있도록 구현 예정
---
# 코드클라이언트 코드
using System.Net; using System.Net.Sockets; using System.Text; namespace SocketTestClient { internal class Program { static void Main(string[] args) { IPAddress iPAddress = Dns.GetHostAddresses(Dns.GetHostName())[1]; IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, 7777); var serverSession = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); serverSession.Connect(iPEndPoint); serverSession.Send(Encoding.UTF8.GetBytes("Hello")); } } }
서버 코드using System.Net; using System.Net.Sockets; using System.Text; namespace SocketTestSever { internal class Program { static Socket acceptSocket; static void Main(string[] args) { IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Any, 7777); acceptSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); acceptSocket.Bind(iPEndPoint); acceptSocket.Listen(10); OnAcceptAsync(); while (true) { Thread.Sleep(100); ; } } public static void OnAcceptAsync() { SocketAsyncEventArgs e = new SocketAsyncEventArgs(); e.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptAsyncComplete); if (!acceptSocket.AcceptAsync(e)) { OnAcceptAsyncComplete(null, e); } } public static void OnAcceptAsyncComplete(object? obj, SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { var clientSocket = e.AcceptSocket; if (clientSocket == null) return; new ClientSession(clientSocket); OnAcceptAsync(); } else { Console.WriteLine(e.SocketError.ToString()); } } } public class ClientSession { const int BUFFER_SIZE = 1024; byte[] _buffer; Socket _socket; public ClientSession(Socket socket) { _buffer = new byte[BUFFER_SIZE]; _socket = socket; OnRecvAsync(); } public void OnRecvAsync() { SocketAsyncEventArgs e = new SocketAsyncEventArgs(); e.Completed += new EventHandler<SocketAsyncEventArgs>(OnRecvAsyncComplete); e.SetBuffer(_buffer); if (!_socket.ReceiveAsync(e)) OnRecvAsyncComplete(null, e); } public void OnRecvAsyncComplete(object? obj, SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success && e.BytesTransferred != 0) { string msg = Encoding.UTF8.GetString(_buffer, 0, e.BytesTransferred); Console.WriteLine(msg); OnSendAsync(msg); OnRecvAsync(); } else { Console.WriteLine(e.SocketError.ToString()); } } public void OnSendAsync(string msg) { SocketAsyncEventArgs args = new SocketAsyncEventArgs(); args.Completed += new EventHandler<SocketAsyncEventArgs>(OnSendAsyncComplete); args.SetBuffer(_buffer); if (!_socket.SendAsync(args)) OnSendAsyncComplete(null, args); } public void OnSendAsyncComplete(object? obj, SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success && e.BytesTransferred != 0) { _buffer.Initialize(); } else { Console.WriteLine(e.SocketError.ToString()); } } } }
---
# 후기- 클라이언트에 특정 메시지만 보내고 서버는 받은 메시지를 서버에 출력하도록 구현했다.
서버 실행 후 클라이언트 실행 시 서버 콘솔 화면 - ConnectionReset 같은 경우 아마 클라이언트에서 연결 시도 후 연결 종료를 하지 않아 뜨는 메시지로 예상된다.
- 클라이언트에서 IPEndPoint 객체를 생성할 시 DNS클래스의 메소드로 ip를 얻고 서버에 연결을 시도해야 됬는데 서버처럼 IpEndPoint의 인수를 Any로 해놓고 왜 안될까 생각하는 기행도 벌였다.
- 내일도 코드 작성 하자
'C#' 카테고리의 다른 글
04/06 단일연결리스트 Add구현 및 인덱서 사용 연습 (0) 2021.04.06