대학원 일기

소캣 본문

School/Network Programming

소캣

대학원생(노예) 2023. 8. 25. 12:36

C 소캣

  • 소캣이란
    • 응용프로그램을 개발할 때 TCP/UDP 또는 IP(raw socket)를 이용하여 프로그램을 개발 할 수 있도록 지원
    • 응용프로그램 개발하기 위해 하위 계층 프로토콜을 사용할 수 있도록 제공
      • TCP: mail, web, ftp, telnet 등 신뢰성 있는 전송이 필요한 경우
      • UDP: DNS, 실시간 스트리밍 서비스, 등 connectionless 전송 이 필요한 경우
      • IP: ping, traceroute 같은 IP 계층을 이용한 프로그램일 경우
    • 유닉스/리눅스에서의 소켓 인터페이스
      • 파일 입출력(I/O)과 유사한 구조
      • 유닉스/리눅스에서 다음과 같이 파일을 오픈하면
        • fd = open("sample.txt", O_RDONLY)
        • 양의 정수값을 리턴하는데 이를 파일 디스크립터(file descriptor, 일종의 포인터)라고 하고 프로그 램에서 이 오픈된 파일을 액세스할 때 이 파일 디스크립터를 사용
        • read(fd, buf, 512)
    • 소켓 디스크립터
      • sd = socket(AF_INET, SOCK_STREAM, 0)
  • 연결 절차

  • 소캣 생성 함수
    • int socket(int family, int type, int protocol)
      • Family
        • AF_INET: AF_INET (인터넷 주소 체계)  주로 사용
        • AF_UNIX (유닉스 주소 체계)
        • AF_INET6 (128비트 IPv6 주소 체계)  IPv6일 때 사용
      • Type
        • 연결형
            1. SOCK_STREAM
        • 비연결형
            1. SOCK_DGRAM
      • Protocal
        • 소켓 지원 프로그램 지정, 보통 0 사용
  • 소켓 주소를 담는 구조체
    • in_adddr inet_addr(const char *string) 문자열을 32비트 정수 인터넷 주소 형태로 변환하는 함수
    • uint32 htonl(uint32) 리틀 엔디안에서 빅 엔디안으로 변환하는 함수 long 형으로
    • uint16 htons(uint16) short 형으로
    • int atoi(string) 문자열을 정수로 변환하는 함수
  • struct sockaddr { u_short sa_family; /* address family */ char sa_data[14]; /* address */ }; struct sockaddr_in { short sin_family; /* address family */ u_short sin_port;/* 16비트 포트번호 */ struct in_addr sin_addr;/* 32비트 IP 주소*/ char sin_zero[8];/* 더미 문자열: 전체 크기를 sockaddr */ /* 구조체와동일한 16바이트로 하기위한 */ }; • 1byte = char • 2byte = short • 4byte = long
  • 빅 엔디안(통신)과 리틀 엔디안(계산)의 차이

  • 메모리에 값을 저장 하는 방식
    • 리틀 엔디안 little endian: 주로 계산을 하는 PC에서 사용
    • : 값을 작은 바이트 부분부터 메모리에 저장
    • 빅 엔디안 big endian
    • : 큰 부분부터 메모리에 저장 : 주로 통신에서 사용
  • 소켓과 주소를 묶어주는 함수 bind()
    • *int bind(int socket_fd,(struct sockaddr )&server_addr,sizeof(server_addr));
      • 외부에서 소켓으로 접속하기 위해서는 생성한 소켓과 사용할 주소를 묶어주는 작업이 서버에서는 필요
      • 클라이언트에서 서버의 주소와 포트 정보를 이용하여 연결 접속 시도하기 때문
      • 성공시0실패시-1
  • 클라이언트의 연결을 대기하는 listen()
    • int listen(int s, int backlog);
      • 클라이언트에서 이 소켓으로 연결요청(connect())하면 TCP 연결을 설정하고 서버에서 연결을 받아들이기 위해 accept() 수행
    • int s : 소켓 번호
    • int backlog : 연결을 기다릴 수 있는 클라이언트의 최대 수
  • 클라이언트의 연결을 수락하는 accept()
    • **int accept(int s, struct sockaddr addr,int addrlen);
      • 성공하면 클라이언트와 통신할 수 있는 새로운 소켓이 생성하여 반환된다 (실패시 -1)
      • 서버는 이 후로는 이 소켓으로 클라이언트와 통신하게 됨
    • int s : 소켓 번호
    • struct sockaddr *addr : 연결 요청을 한 클라이언트의 소켓주소 구조체
    • int *addrlen : *addr 구조체 크기의 포인터
  • 송신 함수
    • int send(int s, char * buf, int length, int flags)
      • int send(int s, char * buf, int length, int flags)
      • int s : 소켓,
      • char *buf: 전송할 데이터
      • int length: 데이터 길이
      • int flags: 0반환값: 보낸 바이트 수, 음수면 실패
    • int write(int s, const void buf, int length)*
      • int s: 소켓
      • buf: 전송할 데이터
      • length: 데이터 길이
      • 반환값: 보낸 바이트 수, 음수면 실패
      write(client_fd, buffer, msg_size);
      
  • 수신 함수
    • int recv(int s, char * buf, int length, int flags)
      • int s : 소켓,
      • char *buf: 전송할 데이터
      • int length: 데이터 길이
      • int flags: 0반환값: 받은 바이트 수, 음수면 실패
    • int read(int s, const void buf, int length)*
      • int s: 소켓
      • buf: 전송할 데이터
      • length: 데이터 길이 반환값: 받은 바이트 수, 음수면 실패
      msg_size = read(client_fd, buffer, BUF_LEN);
      
  • TCP에서 송수신
    • write() 또는 send()실행하면 송신
      1. TCP의 송신 버퍼로 데이터가 들어감
      2. 송신 버퍼가 full 이면 write() send() 함수에서 대기
      3. 버퍼가 비면 버퍼로 데이터 전송
      4. 버퍼에 데이터가 다 들어가면 write() send() 반환
    • read() 또는 recv()실행하면 수신 대기
      1. 이 문장을 수행하면 소켓을 통해 데이터가 수신 버퍼에 도착할 때 까지 대기
      2. 수신버퍼에 데이터가 도착하면 수신 반환
      *** accept() 와 수신 부분에서 대기 발생**
  • 종료함수
    • int close(int s)
      • int s : 소켓,반환값: 보낸 바이트 수, 음수면 실패
      • 서버나 클라이언트 어느 쪽이든 먼저 호출 가능
      • 서버나 클라이언트의 버퍼에 데이터가 있어 전송 중이면 전송을 끝내고 종료
  • 서버로 연결 요청하는 함수 connect
    • *int connect(int socket,const struct sockaddr addr, int addrlen)
      • 서버가 listen() accept() 호출하여 대기하고 있지 않으면 에러 발생
      • int socket : 소켓 번호(디스크립터)
      • const struct sockaddr *addr : 상대방 서버의 소켓서버 구조체
      • int addrlen : 구조체 *addr의 크기성공 시0,실패 시-1반환

C# 소캣

  • System.Net
    • IPAddress class
      • 32비트 IP 주소 저장: byte[4]
      • 201.203.122.134을 저장하려면
      • IPAddress adAddr = IPAddress.Parse(“201.203.122.134“); Console.WriteLine(ipAddr); IPAddress adAddr2 = new IPAddress(new byte[] {201, 203, 122, 134}); Console.WriteLine(ipAddr2);
      • IPv4, IPv6 모두 제공
      • 보통 서버는 IPv4 사용, 일반 클라이언트는 사설 IP 주소 사용하거나 IPv6 주소 배부 사설 주소 범위
        • 10.0.0.0~10.255.255.255,
        • 172.16.0.0~172.32.255.255,
        • 192.168.0.0~192.168.255.255
    • IPEndPoint class
      • IP 주소와 포트번호
      IPEndPoint endpoint = new IPEndPoint();
      IPEndPoint(IPAddress.Parse(“201.203.122.134“), 9000);
      
    • Dns class
    • IPHostEntry entry = Dns.GetHostEntry(“www.microsoft.com”); foreach (IPAddress ipAddress in entry.AddressList){ Console.WriteLine(ipAddress); }
    • 현재 컴퓨터에 할당된 IP 주소 찾기
    • string myComputer = Dns,GetHostName(); Console.WriteLine(“컴퓨터 이름: ” + myComputer); IPHostEntry entry = Dns.GetHostEntry(myComputer); foreach (IPAddress ipAddress in entry.AddressList){ Console.WriteLine(ipAddress); }
  • System.Net.Sockets.Socket
    • public Socket 클래스
    • public Socket { AddressFamily addressFamily, // 주소 패밀리, AddressFamily.InterNetwork SocketType socketType,// 소켓 타입, SocketType.Stream/Dgram ProtocolType protocolType,// 프로토콜 타입, ProtocolType.Tcp/Udp }
    • 생성자
      • IPv4 TCP
      • socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      • IPv4 UDP
      • socket( AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
      • IPv6 TCP
      • socket( AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
    • Bind()
      • public void Bind (System.Net.EndPoint localEP);
      • Exceptions
        • ArgumentNullException: localEP 값이 null일 떄
        • SocketException: socket에 접속하려 할 때 에러 발생
        • ObjectDisposedException: Socket이 closed되었을 때
        • SecurityException: A caller higher in the call stack does not have permission for the requested operation.
      try { aSocket.Bind(anEndPoint);
      } catch (Exception e) { 
      Console.WriteLine("Winsock error: " + e.ToString()); 
      }
      
    • Listen()
      • public void Listen (int backlog);
      • backlog Int32
        • The maximum length of the pending connections queue.
      • Exceptions
        • SocketException: 소켓 접속하려 할 때 발생하는 에러
        • ObjectDisposedException: 소켓이 이미 닫혔을 때
      • LISTEN causes a connection-oriented Socket
        • To listen for incoming connection attempts.
      • The backlog parameter specifies the number of incoming connections
        • that can be queued for acceptance.
        • To determine the maximum number of connections you can specify, retrieve the MaxConnections (2147483647 )value.
        • Listen does not block.
      • Code
      • // create the socket Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // bind the listening socket to the port IPAddress hostIP =IPAddress.Any; IPEndPoint ep = new IPEndPoint(hostIP, port); listenSocket.Bind(ep); // start listening listenSocket.Listen(backlog);
    • Accept()
      • public Accept ();
        • Creates a new Socket for a newly created connection
        • Returns
          • Socket: A Socket for a newly created connection
      • Exceptions
        • SocketException: 소켓 접속하려 할 때 발생하는 에러
        • ObjectDisposedException: 소켓이 이미 닫혔을 때
        • InvalidOperationException:소켓이 LISTEN 하고 있을 않을 때
          • You must call Bind(EndPoint) and Listen(Int32) before calling Accept()
      Socket mySocket = listenSocket.Accept();
      
    • Connnet()
      • public void Connect (string host, int port);
      • Parameters
        • Host : String, The name of the remote host.
        • port: Int32, The port number of the remote host.
      • Exceptions
        • ArgumentNullException:host is null.
        • ArgumentOutOfRangeException: The port number is not valid.
        • SocketException: An error occurred when attempting to access the socket.
        • ObjectDisposedException: The Socket has been closed.
        • NotSupportedException: This method is valid for sockets in the InterNetwork or InterNetworkV6 families.
        • InvalidOperationException: The Socket has been placed in a listening state by calling Listen(Int32).
      Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
      ProtocolType.Tcp);
      Console.WriteLine("Establishing Connection to {0}", host);
      s.Connect(IPAddress.Parse(“서버주소”), port); 
      Console.WriteLine("Connection established");
      
      • If you are using a connection-oriented protocol such as TCP,
        • the Connect method synchronously establishes a network connection between LocalEndPoint and the specified remote host.
      • If you are using a connectionless protocol,
        • Connect establishes a default remote host.
      • After you call Connect you can
        • send data to the remote device with the Send method, or
        • receive data from the remote device with the Receive method.
      • Connect method will block
        • unless you specifically set the Blocking property to false prior to calling Connect.
        • If you are using a connection-oriented protocol like TCP and you do disable blocking,
          • Connect will throw a SocketException
          • because it needs time to make the connection.
    • Close()
      • public void Close ();
      • Closes the Socket connection and releases all associated resources.
      • The Close method closes the remote host connection and
        • releases all managed and unmanaged resources associated with the Socket.
      • Upon closing, the Connected property is set to false.
      try {
      aSocket.Shutdown(SocketShutdown.Both); }
      finally
      { aSocket.Close(); }
      
    • Shutdown()
      • public void Shutdown (System.Net.Sockets.SocketShutdown how);
      • Parameters• How: SocketShutdown, One of the SocketShutdown values that specifies the operation that will no longer be allowed
      • Exceptions
        • SocketException: An error occurred when attempting to access the socket
        • ObjectDisposedException: The Socket has been closed.
      • public enum SocketShutdown

  • Send()
    • public int Send (byte[] buffer);
      • Sends data to a connected Socket.
      • Parameters
        • Buffer Byte[] An array of type Byte that contains the data to be sent.
      • Returns
        • Int32 The number of bytes sent to the Socket.
      • Exceptions
        • ArgumentNullException buffer is null.
        • SocketException An error occurred when attempting to access the socket.
        • ObjectDisposedException The Socket has been closed.
    • public int Send (byte[] buffer, int size, System.Net.Sockets.SocketFlags socketFlags);
      • Parameters
        • buffer Byte[] An array of type Byte that contains the data to be sent.
        • size Int32 The number of bytes to send.
      • Returns
        • Int32 The number of bytes sent to the Socket.
    • public int Send (byte[] buffer, int offset, int size, System.Net.Sockets.SocketFlags socketFlags);
      • Parameters
        • buffer Byte[] An array of type Byte that contains the data to be sent.
        • Offset Int32 The position in the data buffer at which to begin sending data
        • size Int32 The number of bytes to send.
      • Returns
        • Int32 The number of bytes sent to the Socket.
  • Receive()
    • public int Receive (byte[] buffer);
      • Receives data from a bound Socket into a receive buffer.
      • Parameters
        • Buffer Byte[] An array of type Byte that is the storage location for the received data.
      • Returns
        • Int32 The number of bytes received.
      • Exceptions
        • ArgumentNullException buffer is null.
        • SocketException An error occurred when attempting to access the socket.
        • ObjectDisposedException The Socket has been closed.
        • SecurityException A caller in the call stack does not have the required
    • public int Receive (byte[] buffer, int size,System.Net.Sockets.SocketFlags socketFlags);
      • Parameters
        • Buffer Byte[] An array of type Byte that is the storage location for the received data.
        • Size Int32 The number of bytes to receive.
        • socketFlags SocketFlags A bitwise combination of the SocketFlags values.
      • Returns
        • Int32 The number of bytes received.
    • public int Receive (byte[] buffer, int offset, int size, System.Net.Sockets.SocketFlags socketFlags);
      • Parameters
        • buffer Byte[] An array of type Byte that is the storage location for the received data.
        • offset Int32 The location in buffer to store the received data
        • size Int32 The number of bytes to receive.
        • socketFlags SocketFlags A bitwise combination of the SocketFlags values.
      • Returns
        • int32 The number of bytes received.
  • try/catch 문장은 왜 있는가? 어떨 때 catch 문장이 사용되는가?
  • 위의 본 예제는 서버의 경우 클라이언트의 요청을 기다리는 동안 다른 일을 할 수 있는가?
  • 클라이언트와 서버가 마음대로 데이터를 보낼 수 있는가?
  • 서버가 클라이언트가 보내는 데이터를 받기 위해서는 무슨 일하는가?
  • 여러 명의 클라이언트가 동시에 접속할 수 있는가?
  • 우리가 흔히 쓰는 채팅 프로그램이 되려면 어떤 기능이 추가되어야 할까?

'School > Network Programming' 카테고리의 다른 글

C# Thread  (0) 2023.08.25
HTTP 프로토콜  (0) 2023.04.19
Comments