반응형

* Server Code

 

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#define BUFSIZE 1024
#define PORT_NUM 7000


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")

void ErrorHandling(const char* message);


int main(int argc, char** argv) {

    WSADATA wsaData;
    SOCKET servSock, clntSock;   //SOCKET은 사실 UINT_PTR 형이다.
    SOCKADDR_IN servAddr, clntAddr;


    char message[BUFSIZE]; //Message Buffer
    int strLen;
    int fromLen, nRcv;

    int len = 0;

    
    printf("Port Num: 7000");


    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
        ErrorHandling("Load WinSock 2.2 DLL Error");

    servSock = socket(PF_INET, SOCK_STREAM, 0);
    if (servSock == INVALID_SOCKET)
        ErrorHandling("Socket Error");

    memset(&servAddr, 0, sizeof(SOCKADDR_IN));
    servAddr.sin_family = AF_INET;
    servAddr.sin_port = PORT_NUM;
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(servSock, (struct sockaddr*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
        ErrorHandling("Bind Error");

    if (listen(servSock, 2) == SOCKET_ERROR)
        ErrorHandling("Listen Error");

    fromLen = sizeof(clntAddr);


    clntSock = accept(servSock, (struct sockaddr*)&clntAddr, &fromLen);    //// 클라이언트의 접속 요청을 수락
    if (clntSock == INVALID_SOCKET) {
        ErrorHandling("Accept Error");
    }
    else {
        printf("%s Connection Complete!\n", inet_ntoa(clntAddr.sin_addr));
        printf("Start ...\n");
    }
    closesocket(servSock);



    FILE* image;
    image = fopen("C:/Users/94hsk/Desktop/recv.jpg", "wb");
   
    while ((len = recv(clntSock, message, sizeof(message) - 1, 0)) != 0)
    {
        fwrite(message, sizeof(char), sizeof(message) - 1, image);
        if (feof(image))break;
    }

    fclose(image);
    closesocket(clntSock);
    WSACleanup();

    printf("Close Connection..\n");

    return 0;
}

void ErrorHandling(const char* message) {
    WSACleanup();
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

 

 

 

*Client Code

 

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS

#include <winsock2.h>
#include <stdio.h>

#include <stdlib.h>
#include <conio.h>


#include <WS2tcpip.h>


#pragma comment(lib, "ws2_32.lib")
//#include<arpa/inet.h>



#define BUFSIZE 1024

void ErrorHandling(const char* message);

int main(int argc, char** argv) {

    SOCKET clntSock;    // 소켓 생성
    WSADATA wsaData;
    SOCKADDR_IN servAddr;

    char sAddr[15];
    int sPort;
    int nRcv;
    unsigned int Addr;
    char message[BUFSIZE];
    char message2[BUFSIZE];

    struct hostent* host;

    FILE* fp;
    size_t len;

    fp = NULL;
    fp = fopen("C:/Users/94hsk/Desktop/lena.jpg", "rb");


    if (fp  == NULL)
        ErrorHandling("Image Read Fail");

    printf("Server Address : ");       gets_s(sAddr, sizeof(sAddr));   /// gets_s함수는 입력을 받는 함수로
    printf("Port Number : ");       gets_s(message, sizeof(message));   // 해당 크기만큼의 문자열을 받아 저장한다.
    sPort = atoi(message);  // 문자열을 정수 타입으로 변경해주는 함수이다.
                            // 왜 변경하지?
                            // message에 문자가 들어가면 바로 0을 반환
                            // 문자가 숫자로 시작할 시 숫자 반환
                            // 숫자+문자의 경우 문자 나오기 전까지 숫자 반환
                            // 문자+숫자의 경우 0 반환
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)  // 소캣 사용 전 초기화를 진행하고 초기화 정보를 wasData에 저장
        ErrorHandling("Load WinSock 2.2 DLL Error");    // 초기화 성공하면 0 반환

    clntSock = socket(AF_INET, SOCK_STREAM, 0); // socket(int domain, int Type, int protocol);
                                                // 소캣을 생성한다.
                                                // AF_INET 체계는 주소체계를 사용하며 IPv4인터넷 프로토콜 사용

    if (clntSock == INVALID_SOCKET)
        ErrorHandling("Socket Error");

    memset(&servAddr, 0, sizeof(servAddr)); // memset 함수는 어떤 메모리의 시작점부터 연속된 범위를 어떤 값으로
                                            // 모두 지정하고 싶을때 사용하는 함수
                                // 채우고자 하는 메모리의 시작 주소 : servAddr
                                // 메모리에 채우고자 하는 값 : 0
                                // 채우고자 하는 메모리의 크기 : sizeof(servAddr)
    
    //// SOCKADDR_IN 구조체의 객체 servAddr
    //// 위의 구조체는 IPv4 주소를 저장하는 구조체이다.
    //// 주소 체계, 포트 정보, IPv4 주소 등을 저장한다.
    
    
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = inet_addr(sAddr);
    
    //// SOCKADDR_IN 구조체의 구조체변수 servAddr에 대해 설정을 진행한다.
    //// sin_addr 값에는 IP주소를 나타내는 32비트 정수 탑이의 구조체가 들어간다.
    //// 즉 입력받은 iP주소를 통해 통신을 설정해주는 부분이다.
    void* dst;
    int check;


    //servAddr.sin_port = htons(sPort);
    servAddr.sin_port = (sPort);


    if (connect(clntSock, (struct sockaddr*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR) {
        ErrorHandling("Connection Error");
    }
    else {
        printf("Connect OK!\nStart...\n");
    }


    while (1)
    {
        printf("sending\n");
        len = fread(message2, sizeof(char), BUFSIZE-1, fp);
        send(clntSock, message2, len, 0);
        if (feof(fp))break;
    }
    printf("Sending Done! \n");
    shutdown(clntSock, SD_SEND);

    len = recv(clntSock, message2, BUFSIZE - 1, 0);
    message2[len] = 0;
    puts(message2);

    fclose(fp);

    closesocket(clntSock);
    WSACleanup();           /// 소캣 종료
    printf("Close Connection..\n");

    return 0;
}


void ErrorHandling(const char* message) {
    WSACleanup();
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

 

반응형

'C++' 카테고리의 다른 글

C++ 내부정의, 외부정의, 헤더파일  (0) 2020.01.09
객체지향언어  (0) 2020.01.08

+ Recent posts