본문 바로가기
혼자 코딩(C언어)

c언어 윈도우 기반 TCP/IP 서버 다중 접속 예제 - 002

by 서하란 2022. 8. 8.
반응형
SMALL
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
 
 
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#pragma comment(lib, "ws2_32");
 
#define BUF_SIZE 1024
 
void err_quit(char* message)
{
    LPVOID IpMsgBuf;
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        NULL, WSAGetLastError(),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&IpMsgBuf, 0NULL);
    exit(-1);
}
 
 
int main()
{
    WSADATA wsaData;                    
    SOCKET hServSock, hClntSock;    
    SOCKADDR_IN servAdr, clntAdr;
    TIMEVAL timeout;                    
    fd_set reads, cpyReads;
 
    int adrSz;                            
    int strLen, fdNum, i;                
    char buf[BUF_SIZE];                    
 
 
    if (WSAStartup(MAKEWORD(22), &wsaData) != 0)        
        err_quit("WSAStartup() error!");
    printf("소켓이 생성되었습니다\n");
 
    hServSock = socket(AF_INET, SOCK_STREAM, 0);        
    memset(&servAdr, 0sizeof(servAdr));
    servAdr.sin_family = AF_INET;
    servAdr.sin_addr.s_addr = htonl(INADDR_ANY);
    servAdr.sin_port = htons(5001);
 
 
 
 
    if (bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)        
        err_quit("blind() eroor");
    printf("Bind 완료 되었습니다.\n");
 
 
 
 
    if (listen(hServSock, 5== SOCKET_ERROR)        
        err_quit("listen() eroor");
    printf("connect 연결을 기다리는 중..\n");
 
    FD_ZERO(&reads);                    
    FD_SET(hServSock, &reads);            
 
 
 
 
    while (1)
    {
        cpyReads = reads;                
        timeout.tv_sec = 5;                
        timeout.tv_usec = 5000;            
 
 
 
 
        if ((fdNum = select(0&cpyReads, 00&timeout)) == SOCKET_ERROR) 
            break;
 
        if (fdNum == 0)                    
            continue;
 
        for (i = 0; i < reads.fd_count; i++)        
        {
            if (FD_ISSET(reads.fd_array[i], &cpyReads))        
            {
                if (reads.fd_array[i] == hServSock)            
                {
                    adrSz = sizeof(clntAdr);
                    hClntSock = accept(hServSock, (SOCKADDR*)&clntAdr, &adrSz); 
                    FD_SET(hClntSock, &reads);                
                    printf("connected client: %d \n", hClntSock);
                }
                else
                {                                            
                    memset(buf, 0sizeof(buf));
                    strLen = recv(reads.fd_array[i], buf, BUF_SIZE - 10);
                    if (strLen == 0)
                    {                                        
                        FD_CLR(reads.fd_array[i], &reads);
                        closesocket(cpyReads.fd_array[i]);
                        printf("closed client: %d \n", cpyReads.fd_array[i]);
                    }
                    else
                    {                                        
                        send(reads.fd_array[i], buf, strLen, 0);
                        printf("[TCP/%s:%d] %s\n", inet_ntoa(clntAdr.sin_addr), ntohs(clntAdr.sin_port), buf);
                    }
                }
            }
        }
    }
    closesocket(hServSock);
    WSACleanup();
    return 0;
}
cs

 

 

여러개의 클라이언트를 하나의 서버에 접속시키는 예제

 

멀티플렉싱방식이다

 

다만,

문제 1) 연결이 끊어졌을 때 알림이 없다

문제 2) 과연 파일도 전송이 가능한가?

반응형
LIST

댓글