C

[윈도우 소켓프로그래밍] C 학생정보찾기 확장

돌맹96 2024. 6. 10. 21:37
728x90
반응형

이전 프로젝트에서 UI도 추가하고 몇가지 기능을 추가했다.

이름과 나이 국적 중 하나를 입력하면 전체값을 주게끔 만들었다.

Server 코드다.

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <process.h>
#include <windows.h>
#include <string.h>
#include <ws2tcpip.h>  // for inet_pton

#pragma comment(lib, "ws2_32.lib")
#define BUF_SIZE 100
#define MAX_CLNT 256
#define STD_MAX_NUM 100
#define WHITE 15
#define YELLOW 6
#define BLUE 9

typedef struct student {
    char name[30];
    int age;
    char nation[4];
    char depart[3];
} STUDENT;

void setStudentData(FILE* fp);
unsigned WINAPI HandleClient(void* arg);
void SendMsg(char* msg, int len);

int clientCount = 0;
SOCKET clientSocks[MAX_CLNT];
HANDLE hMutex;
STUDENT students[STD_MAX_NUM];
int std_cnt = 0;

int main(int argc, char* argv[]) {
    FILE* fpin;
    WSADATA wsaData;
    SOCKET serverSock, clientSock;
    SOCKADDR_IN serverAddr, clientAddr;
    int clientAddrSize;
    HANDLE hThread;
    int portNum;

    if (fopen_s(&fpin, "students.txt", "r") != 0) {
        printf("File open error...\n");
        exit(-1);
    }
    setStudentData(fpin);

    printf("Server : Set Server Port number (Please use integer number between 49152 to 65535) : ");
    scanf_s("%d", &portNum);
    WSAStartup(MAKEWORD(2, 2), &wsaData);
    hMutex = CreateMutex(NULL, FALSE, NULL);
    if (hMutex == NULL) {
        printf("Mutex creation failed\n");
        exit(-1);
    }
    serverSock = socket(PF_INET, SOCK_STREAM, 0);
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serverAddr.sin_port = htons(portNum);
    bind(serverSock, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
    listen(serverSock, 5);
    printf("Server : Ready to Client Connection\n");

    while (1) {
        clientAddrSize = sizeof(clientAddr);
        clientSock = accept(serverSock, (SOCKADDR*)&clientAddr, &clientAddrSize);
        WaitForSingleObject(hMutex, INFINITE);
        clientSocks[clientCount++] = clientSock;
        ReleaseMutex(hMutex);

        char clientIP[INET_ADDRSTRLEN];
        InetNtopA(AF_INET, &clientAddr.sin_addr, clientIP, INET_ADDRSTRLEN);
        hThread = (HANDLE)_beginthreadex(NULL, 0, HandleClient, (void*)&clientSock, 0, NULL);
        printf("Connected Client IP : %s\n", clientIP);
    }

    closesocket(serverSock);
    WSACleanup();
    return 0;
}

unsigned WINAPI HandleClient(void* arg) {
    SOCKET clientSock = *((SOCKET*)arg);
    int strLen = 0, i;
    char msg[BUF_SIZE] = "";
    char result[BUF_SIZE] = "";

    while (1) {
        strLen = recv(clientSock, msg, BUF_SIZE - 1, 0);
        msg[strLen] = '\0';
        printf("Server : Received Message -> %s\n", msg);

        if (!strcmp(msg, "q")) {
            send(clientSock, "q", 1, 0);
            break;
        }
        else if (!strncmp(msg, "LOGIN", 5)) {
            // Implement login functionality
        }
        else if (!strncmp(msg, "FIND_ID", 7)) {
            // Implement find ID functionality
        }
        else if (!strncmp(msg, "FIND_PW", 7)) {
            // Implement find PW functionality
        }
        else if (!strncmp(msg, "SIGN_UP", 7)) {
            // Implement sign up functionality
        }
        else {
            // Default case, handle student info request
            for (i = 0; i < std_cnt; i++) {
                if ((strncmp(msg, "NAME ", 5) == 0 && strcmp(msg + 5, students[i].name) == 0) ||
                    (strncmp(msg, "AGE ", 4) == 0 && atoi(msg + 4) == students[i].age) ||
                    (strncmp(msg, "NATION ", 7) == 0 && strcmp(msg + 7, students[i].nation) == 0)) {
                    sprintf_s(result, BUF_SIZE, "%s,%d,%s,%s", students[i].name, students[i].age, students[i].nation, students[i].depart);
                    send(clientSock, result, strlen(result), 0);
                    printf("Send Result\n");
                    break;
                }
            }
            if (i == std_cnt) {
                sprintf_s(result, BUF_SIZE, "No Result");
                send(clientSock, result, strlen(result), 0);
                printf("Send No Result Message\n");
            }
        }
    }

    printf("client left the Server\n");
    WaitForSingleObject(hMutex, INFINITE);
    for (i = 0; i < clientCount; i++) {
        if (clientSock == clientSocks[i]) {
            while (i++ < clientCount - 1)
                clientSocks[i] = clientSocks[i + 1];
            break;
        }
    }
    clientCount--;
    ReleaseMutex(hMutex);
    closesocket(clientSock);
    return 0;
}

void setStudentData(FILE* fp) {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    printf("Server : Initiation of Data Load \n");
    while (!feof(fp)) {
        fscanf_s(fp, "%s %d %s %s", students[std_cnt].name, (unsigned)_countof(students[std_cnt].name), &students[std_cnt].age, students[std_cnt].nation, (unsigned)_countof(students[std_cnt].nation), students[std_cnt].depart, (unsigned)_countof(students[std_cnt].depart));
        std_cnt = std_cnt + 1;
    }
    printf("Server : End of Data Loading \n");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), WHITE);
}

Client 코드다.

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>  // for inet_pton
#include <string.h>

#pragma comment(lib, "ws2_32.lib")
#define BUF_SIZE 100

void printMenu() {
    printf("********** 검색시스템 **********\n");
    printf("1. FIND BY NAME\n");
    printf("2. FIND BY AGE\n");
    printf("3. FIND BY NATION\n");
    printf("0. EXIT\n");
    printf("**************************\n");
    printf("Choose an option: ");
}

int main() {
    WSADATA wsaData;
    SOCKET sock;
    SOCKADDR_IN serv_addr;
    char msg[BUF_SIZE];
    int str_len;
    int option;
    char ip[INET_ADDRSTRLEN];
    int port;

    printf("Enter server IP: ");
    scanf_s("%s", ip, (unsigned)_countof(ip));
    printf("Enter server port: ");
    scanf_s("%d", &port);

    WSAStartup(MAKEWORD(2, 2), &wsaData);
    sock = socket(PF_INET, SOCK_STREAM, 0);

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    if (inet_pton(AF_INET, ip, &serv_addr.sin_addr) <= 0) {
        printf("Invalid address/ Address not supported \n");
        return -1;
    }
    serv_addr.sin_port = htons(port);

    if (connect(sock, (SOCKADDR*)&serv_addr, sizeof(serv_addr)) == -1) {
        perror("connect() error");
        exit(1);
    }

    while (1) {
        printMenu();
        scanf_s("%d", &option);
        getchar();  // Clear newline character from input buffer

        memset(msg, 0, BUF_SIZE);  // Initialize the msg buffer

        switch (option) {
        case 1:
            printf("Enter name: ");
            fgets(msg + 5, BUF_SIZE - 5, stdin);  // Leave space for "NAME "
            msg[strcspn(msg, "\n")] = 0;  // Remove newline character
            sprintf_s(msg, BUF_SIZE, "NAME %s", msg + 5);
            send(sock, msg, strlen(msg), 0);
            break;
        case 2:
            printf("Enter age: ");
            fgets(msg + 4, BUF_SIZE - 4, stdin);  // Leave space for "AGE "
            msg[strcspn(msg, "\n")] = 0;  // Remove newline character
            sprintf_s(msg, BUF_SIZE, "AGE %s", msg + 4);
            send(sock, msg, strlen(msg), 0);
            break;
        case 3:
            printf("Enter nation: ");
            fgets(msg + 7, BUF_SIZE - 7, stdin);  // Leave space for "NATION "
            msg[strcspn(msg, "\n")] = 0;  // Remove newline character
            sprintf_s(msg, BUF_SIZE, "NATION %s", msg + 7);
            send(sock, msg, strlen(msg), 0);
            break;
        case 0:
            send(sock, "q", 1, 0);
            closesocket(sock);
            WSACleanup();
            return 0;
        default:
            printf("Invalid option. Please try again.\n");
            continue;
        }

        str_len = recv(sock, msg, BUF_SIZE - 1, 0);
        msg[str_len] = '\0';
        printf("Server: %s\n", msg);
    }

    closesocket(sock);
    WSACleanup();
    return 0;
}

결과화면

728x90
반응형