파일전송 프로그래밍 도와주세요!!
블1랙캣
filereceiver.cpp
#include winsock2.h
#include stdlib.h
#include stdio.h
#define BUFSIZE 4096
// 소켓 함수 오류 출력 후 종료
void err_quit(char *msg)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
MessageBox(NULL, (LPCTSTR)lpMsgBuf, msg, MB_ICONERROR);
LocalFree(lpMsgBuf);
exit(-1);
}
// 소켓 함수 오류 출력
void err_display(char *msg)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
printf([%s] %s, msg, (LPCTSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
}
// 사용자 정의 데이터 수신 함수
int recvn(SOCKET s, char *buf, int len, int flags)
{
int received;
char *ptr = buf;
int left = len;
while(left 0){
received = recv(s, ptr, left, flags);
if(received == SOCKET_ERROR)
return SOCKET_ERROR;
else if(received == 0)
break;
left -= received;
ptr += received;
}
return (len - left);
}
int main(int argc, char* argv[])
{
int retval;
// 윈속 초기화
WSADATA wsa;
if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
return -1;
// socket()
SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, 0);
if(listen_sock == INVALID_SOCKET) err_quit(socket());
// bind()
SOCKADDR_IN serveraddr;
ZeroMemory(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(2007);//포트 번호
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
retval = bind(listen_sock, (SOCKADDR *)&serveraddr, sizeof(serveraddr));
if(retval == SOCKET_ERROR) err_quit(bind());
// listen()
retval = listen(listen_sock, SOMAXCONN);
if(retval == SOCKET_ERROR) err_quit(listen());
// 데이터 통신에 사용할 변수
SOCKET client_sock;
SOCKADDR_IN clientaddr;
int addrlen;
char buf[BUFSIZE];
while(1){
// accept()
addrlen = sizeof(clientaddr);
client_sock = accept(listen_sock, (SOCKADDR *)&clientaddr, &addrlen);
if(client_sock == INVALID_SOCKET){
err_display(accept());
continue;
}
printf(\nFileSender 접속: IP 주소=%s, 포트 번호=%d\n,
inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
// 파일 이름 받기
char filename[256];
ZeroMemory(filename, 256);
retval = recvn(client_sock, filename, 256, 0);
if(retval == SOCKET_ERROR){
err_display(recv());
closesocket(client_sock);
continue;
}
printf(- 받을 파일 이름: %s\n, filename);
// 파일 크기 받기
int totalbytes;
retval = recvn(client_sock, (char *)&totalbytes, sizeof(totalbytes), 0);
if(retval == SOCKET_ERROR){
err_display(recv());
closesocket(client_sock);
continue;
}
printf(- 받을 파일 크기: %d\n, totalbytes);
// 파일 열기
FILE *fp = fopen(filename, wb);
if(fp == NULL){
perror(파일 입출력 오류);
closesocket(client_sock);
continue;
}
// 파일 데이터 받기
int numtotal = 0;
while(1){
retval = recvn(client_sock, buf, BUFSIZE, 0);
if(retval == SOCKET_ERROR){
err_display(recv());
break;
}
else if(retval == 0)
break;
else{
fwrite(buf, 1, retval, fp);
if(ferror(fp)){
perror(파일 입출력 오류);
break;
}
numtotal += retval;
}
}
fclose(fp);
// 전송 결과 출력
if(numtotal == totalbytes)
printf(- 파일 전송 완료!\n);
else
printf(- 파일 전송 실패!\n);
// closesocket()
closesocket(client_sock);
printf(FileSender 종료: IP 주소=%s, 포트 번호=%d\n,
inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
}
// closesocket()
closesocket(listen_sock);
// 윈속 종료
WSACleanup();
return 0;
}
filesender.cpp
#include winsock2.h
#include stdlib.h
#include stdio.h
#define BUFSIZE 4096
// 소켓 함수 오류 출력 후 종료
void err_quit(char *msg)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
MessageBox(NULL, (LPCTSTR)lpMsgBuf, msg, MB_ICONERROR);
LocalFree(lpMsgBuf);
exit(-1);
}
// 소켓 함수 오류 출력
void err_display(char *msg)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
printf([%s] %s, msg, (LPCTSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
}
int main(int argc, char* argv[])
{
int retval;
if(argc 2){
fprintf(stderr, Usage: %s FileName\n, argv[0]);
return -1;
}
// 윈속 초기화
WSADATA wsa;
if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
return -1;
// socket()
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == INVALID_SOCKET) err_quit(socket());
// connect()
SOCKADDR_IN serveraddr;
ZeroMemory(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(9000);
serveraddr.sin_addr.s_addr = inet_addr(127.0.0.1);
retval = connect(sock, (SOCKADDR *)&serveraddr, sizeof(serveraddr));
if(retval == SOCKET_ERROR) err_quit(connect());
// 파일 열기
FILE *fp = fopen(argv[1], rb);
if(fp == NULL){
perror(파일 입출력 오류);
return -1;
}
// 파일 이름 보내기
char filename[256];
ZeroMemory(filename, 256);
sprintf(filename, argv[1]);
retval = send(sock, filename, 256, 0);
if(retval == SOCKET_ERROR) err_quit(send());
// 파일 크기 얻기
fseek(fp, 0, SEEK_END);
int totalbytes = ftell(fp);
// 파일 크기 보내기
retval = send(sock, (char *)&totalbytes, sizeof(totalbytes), 0);
if(retval == SOCKET_ERROR) err_quit(send());
// 파일 데이터 전송에 사용할 변수
char buf[BUFSIZE];
int numread;
int numtotal = 0;
// 파일 데이터 보내기
rewind(fp); // 파일 포인터를 제일 앞으로 이동
while(1){
numread = fread(buf, 1, BUFSIZE, fp);
if(numread 0){
retval = send(sock, buf, numread, 0);
if(retval == SOCKET_ERROR){
err_display(send());
break;
}
numtotal += numread;
}
else if(numread == 0 && numtotal == totalbytes){
printf(파일 전송 완료!: %d 바이트\n, numtotal);
break;
}
else{
perror(파일 입출력 오류);
break;
}
}
fclose(fp);
// closesocket()
closesocket(sock);
// 윈속 종료
WSACleanup();
return 0;
}이 두개의 소스를 수정해야 합니다.
IP:loopback 주소 사용, 포트:2007 전송패킷의 크기:100바이트 Transport:TCP
클라이언트:
1.서버에 접속하여 파일 전송을 요구한다.
2.패킷단위로 파일을 전송받는다.
3.매 패킷마다 ACK메시지를 클라이언트에서 서버로 보낸다.
4.받은 패킷을 표준입출력장치에 출력한다. 패킷 내용을 출력하는 기능을 thread로 설계시 가산점 있음. Thread를 위한 동기화 기능 추가시 추가 가산점.
5.모든 패킷을 받은후 접속 종료
서버:
1.클라이언트의 접속을 승인하고 파일을 100바이트의 크리단위로 클라이언트에게 전송한다.
2.ACK메시지를 받은 후 재전송 또는 다음 패킷 전송을 결정한다.
3.연결해지 요청이 오면 연결해지한다.