==================================================================================================
간단한 파일 전송 구현 ...
서버가 소켓을 완전 종료(close/closesocket) 하면서 EOF를 전송하게 되면, 클라이언트로부터 데이터를
수신 받지 못한다. EOF도 보내고, 데이터도 수신할 수 있는 상태가 되게 하기 위해 Half-Close를 사용한다.
==================================================================================================
[실행화면]
- receive.dat
==================================================================================================
[소스코드]
- server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib") // winsock2를 사용하기 위함
#define BUF_SIZE 1024
void dll_load(WSADATA *wsaData);
void conn_init(SOCKET *serv_sock, SOCKADDR_IN *serv_addr, int port);
void accept_client(SOCKET *clnt_sock, SOCKET *serv_sock, SOCKADDR_IN *clnt_addr, int *size);
void conn_finish(SOCKET *clnt_sock);
void ErrorHandling(char *message);
int main(int argc, char *argv[])
{
WSADATA wsaData;
SOCKET hServSock, hClntSock;
SOCKADDR_IN serv_addr, clnt_addr;
FILE *fp;
char message[BUF_SIZE];
int clntAddrSize, len;
if(argc != 2)
{
printf("Usage : %s <PORT>", argv[0]);
exit(0);
}
dll_load(&wsaData);
memset(&serv_addr, 0, sizeof(serv_addr));
conn_init(&hServSock, &serv_addr, atoi(argv[1]));
fp = fopen("endian_conv.c", "r");
if(fp == NULL)
ErrorHandling("File open Error");
if(bind(hServSock, (SOCKADDR *)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR)
ErrorHandling("bind() Error!");
if(listen(hServSock, 5) == SOCKET_ERROR)
ErrorHandling("listen() Error!");
clntAddrSize = sizeof(clnt_addr);
accept_client(&hClntSock, &hServSock, &clnt_addr, &clntAddrSize);
while(1)
{
len = fread(message, sizeof(char), BUF_SIZE, fp);
send(hClntSock, message, len, 0);
if(feof(fp))
break;
}
if(shutdown(hClntSock, SD_SEND) == SOCKET_ERROR) // Half Close
ErrorHandling("shutdown() Error!");
len = recv(hClntSock, message, BUF_SIZE-1, 0);
message[len] = 0;
fputs(message, stdout);
fclose(fp);
conn_finish(&hClntSock);
return 0;
}
void dll_load(WSADATA *wsaData) // Winsock 2.2 dll Load
{
if(WSAStartup(MAKEWORD(2, 2), wsaData) != 0)
ErrorHandling("WSAStartup() Error!");
}
// 네트워크 초기 세팅
void conn_init(SOCKET *serv_sock, SOCKADDR_IN *serv_addr, int port)
{
*serv_sock = socket(PF_INET, SOCK_STREAM, 0);
if(*serv_sock == INVALID_SOCKET)
ErrorHandling("socket() Error!");
serv_addr->sin_family = AF_INET;
serv_addr->sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr->sin_port = htons(port);
}
// 클라이언트의 접속을 처리
void accept_client(SOCKET *clnt_sock, SOCKET *serv_sock, SOCKADDR_IN *clnt_addr, int *size)
{
*clnt_sock = accept(*serv_sock, (SOCKADDR *)clnt_addr, size);
if(*clnt_sock == INVALID_SOCKET)
ErrorHandling("accept() Error!");
}
// 네트워크 연결 종료
void conn_finish(SOCKET *clnt_sock)
{
closesocket(*clnt_sock);
WSACleanup();
}
// 에러 처리 함수
void ErrorHandling(char *message)
{
fputs(message, stdout);
fputc('\n', stderr);
exit(1);
}
-----------------------------------------------------------------------------------------------
- client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib") // winsock2를 사용하기 위함
#define BUF_SIZE 1024
void dll_load(WSADATA *wsaData);
void conn_init(SOCKET *sock, SOCKADDR_IN *serv_addr, char *IP_Address, int port);
void conn_finish(SOCKET *sock);
void ErrorHandling(char *message);
int main(int argc, char *argv[])
{
WSADATA wsaData;
SOCKET sock;
SOCKADDR_IN serv_addr;
FILE *fp;
char message[BUF_SIZE];
int len;
if(argc != 3)
{
printf("Usage : %s <IP> <PORT>\n", argv[0]);
exit(0);
}
dll_load(&wsaData);
memset(&serv_addr, 0, sizeof(serv_addr));
conn_init(&sock, &serv_addr, argv[1], atoi(argv[2]));
if(connect(sock, (SOCKADDR *)&serv_addr, sizeof(serv_addr)) == SOCKET_ERROR)
ErrorHandling("connect() Error!");
if((fp = fopen("./receive.dat", "w")) == NULL)
ErrorHandling("File Open failed!");
while((len = recv(sock, message, BUF_SIZE, 0)) != 0)
fwrite(message, sizeof(char), len, fp);
send(sock, "Thank you\n", 10, 0);
fclose(fp);
conn_finish(&sock);
return 0;
}
void dll_load(WSADATA *wsaData) // Winsock 2.2 dll Load
{
if(WSAStartup(MAKEWORD(2, 2), wsaData) != 0)
ErrorHandling("WSAStartup Error!");
}
// 네트워크 초기 세팅
void conn_init(SOCKET *sock, SOCKADDR_IN *serv_addr, char *IP_Address, int port)
{
*sock = socket(PF_INET, SOCK_STREAM, 0);
if(*sock == INVALID_SOCKET)
ErrorHandling("socket() Error!");
serv_addr->sin_family = AF_INET;
serv_addr->sin_addr.s_addr = inet_addr(IP_Address);
serv_addr->sin_port = htons(port);
}
// 네트워크 연결 종료
void conn_finish(SOCKET *sock)
{
closesocket(*sock);
WSACleanup();
}
// 에러 처리 함수
void ErrorHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
==================================================================================================
'IT_Programming > Network Programming' 카테고리의 다른 글
[I/O Multiplexing] select를 이용한 멀티플렉싱 구현 (Ver. Win / Linux) (0) | 2009.07.07 |
---|---|
[펌] 멀티 프로세스 / 멀티 쓰레드 / 멀티 플렉싱 기법의 장점과 단점 (0) | 2009.07.02 |
[WinSock] 열린 포트 검색하기 (0) | 2009.07.01 |
[UDP] strftime()를 이용해서 날짜와 시간 문자열 구하기 (0) | 2009.06.30 |
[Linux C] 에코 서버, 에코 클라이언트 만들기 (sinal intterrupt 적용) (0) | 2009.06.30 |