질문사항이 있어서 이렇게 올립니다 답변부탁드립니다.

ascpm의 이미지

소켓프로그램으로
서버와 클라이언트간 파일을 주고 받으려고 한건데요. 문제가 조그 있어서 이렇게 올립니다.
아래는 소스코드입니다.

서버
#include
#include
#include
#include
#include
#include

#include
#include
#include
#include
#include
#include
#include

#include "mydirinfo.h"

#define SOCKADDR_IN struct sockaddr_in
#define SOCKADDR struct sockaddr

#define SV_FILE_NAME "svarlist"
#define DIFF_FILE_NAME "difflist"

#define PORT_NUM 7777
#define LOG_MAX 5
#define BUFF_SIZE 1024
#define DIR_PATH "/var"

int main(int argc, char *argv[])
{
SOCKADDR_IN sAdd, cAdd;
char buf[BUFF_SIZE];
int sFd, cFd;
int cLen, fd;
int recvCount;

// 이것은 제가 라이브러리로 따로 만들어 놓은 함수입니다.
// 해당 디렉토리의 파일 정보를 읽어오는 역할을 하는 함수입니다.
dirInfo(DIR_PATH, SV_FILE_NAME);

if ((sFd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket error");
exit(1);
}

bzero(&sAdd, sizeof(sAdd));
sAdd.sin_family = AF_INET;
sAdd.sin_addr.s_addr = htonl(INADDR_ANY);
sAdd.sin_port = htons(PORT_NUM);

if ((bind(sFd, (SOCKADDR *)&sAdd, sizeof(sAdd))) == -1)
{
perror("bind error");
exit(1);
}

if ((listen(sFd, LOG_MAX)) == -1)
{
perror("listen error");
exit(1);
}

while (1)
{
cLen = sizeof(cAdd);

if ((cFd = accept(sFd, (SOCKADDR *)&cAdd, &cLen)) == -1)
{
perror("accept error");
exit(1);
}

if ((fd = open(SV_FILE_NAME, O_RDONLY)) == -1)
{
perror("file open error");
exit(1);
}

while (1)
{
memset(buf, 0, BUFF_SIZE);

if (read(fd, buf, BUFF_SIZE) > 0)
send(cFd, buf, strlen(buf), 0);
else
break;
}

printf("%s 전송 완료\n\n", SV_FILE_NAME);

close(fd);

// 여기서 클라이언트쪽에서 서버에서 보낸 정보를 모두 읽을때 까지
// 기다리는 코드를 넣어야 할 것 같은데요...
/*
if ((fd = open(DIFF_FILE_NAME, O_WRONLY | O_CREAT | O_TRUNC)) == -1)
{
perror("file open error");
exit(1);
}

while (1)
{
memset(buf, 0, BUFF_SIZE);

if((recvCount = recv(cFd, buf, BUFF_SIZE, 0)) > 0)
write(fd, buf, recvCount);
else
break;
}

printf("%s 로 파일받기 완료\n\n", DIFF_FILE_NAME);
*/
close(fd);
close(cFd);
}
}

클라이언트

#include
#include
#include
#include
#include
#include

#include
#include
#include
#include
#include
#include
#include

#include "mydirinfo.h"
#include "myfilecompare.h"

#define SOCKADDR_IN struct sockaddr_in
#define SOCKADDR struct sockaddr

#define SV_FILE_NAME "svarlist"
#define CL_FILE_NAME "cvarlist"
#define DIFF_FILE_NAME "difflist"

#define PORT_NUM 7777
#define BUFF_SIZE 1024
#define DIR_PATH "/var"

int main(int argc, char *argv[])
{
SOCKADDR_IN sAdd;
char buf[BUFF_SIZE];
int sFd;
int fd;
int recvCount;

if (argc != 2)
{
printf("Usage : filename serverIPaddress\n");
exit(0);
}

dirInfo(DIR_PATH, CL_FILE_NAME);

if ((sFd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket error");
exit(1);
}

bzero(&sAdd, sizeof(sAdd));
sAdd.sin_family = AF_INET;
sAdd.sin_addr.s_addr = inet_addr(argv[1]);
sAdd.sin_port = htons(PORT_NUM);

if (connect(sFd, (SOCKADDR *)&sAdd, sizeof(sAdd)) == -1)
{
perror("connect error");
exit(1);
}
else
printf("서버와 연결되었습니다.\n\n");

if ((fd = open(SV_FILE_NAME, O_WRONLY | O_CREAT | O_TRUNC)) == -1)
{
perror("file open error");
exit(1);
}

while (1)
{
memset(buf, 0, BUFF_SIZE);

if ((recvCount = recv(sFd, buf, BUFF_SIZE, 0)) > 0)
write(fd, buf, recvCount);
else
break;
}

// 제 생각대로라면 서버쪽에서 보낸 파일을 받고서 아래 코드들을 실행하여
// 서버 쪽으로 파일을 보내야 하는데 이 주석 밑으로는 실행이 안되고
// 한없이 기다리는군요.
printf("%s 로 파일받기 완료\n\n", SV_FILE_NAME);
close(fd);

fileCompare(SV_FILE_NAME, CL_FILE_NAME);

if ((fd = open(DIFF_FILE_NAME, O_RDONLY)) == -1)
{
perror("filen open error");
exit(1);
}

while (1)
{
memset(buf, 0, BUFF_SIZE);

if (read(fd, buf, BUFF_SIZE) > 0)
send(sFd, buf, strlen(buf), 0);
else
break;
}

printf("%s 전송 완료\n\n", DIFF_FILE_NAME);
close(fd);
close(sFd);
}

서버쪽에서 파일을 보내고 클라이언트쪽에서는 그 파일을 받아 클라이언트쪽의 파일과 비교하여
다시 서버쪽으로 파일을 보내는 프로그램인데요.

실행시 서버쪽에서 파일은 정상적으로 보내지는데 클라이언트 쪽에서 파일을 받지 못하는군요.(정확히 말하면 파일은 받는거 같은데 서버쪽에서 바로 클라이언트쪽의 파일을 받는 부분으로 넘어가서 클라이언트쪽의 실행이 안돼는것 같습니다.)

서버쪽의 코딩에서 문단주석을 해놓으면(위에서 해놓은대로) 실행은 됩니다.

서버쪽과 클라이언트쪽에서 서로 파일을 주고받으려면 어떤 방법이 없을까요?
답변 부탁드립니다.

ascpm의 이미지

부탁드려요.

kslee80의 이미지

클라이언트에서 파일을 받는데 사용한 while() 문이 끝나고 그 이후 부분의 코드가 실행되려면 어떻게 되어야 할까요?

현재 짜여져 있는 대로라면 recv() 가 <=0 이여야 while() 문이 종료되는데,
recv() 가 <=0 인 경우는 어떤 경우일지 생각해 보시면 되겠습니다.

ascpm의 이미지

위에님 그게 문제가 아니라..

bushi의 이미지

... 이제 문제가 2개가 되었습니다.

서버측에서 send() 의 리턴값을 확신하시면,
서버가 보내지 못했는지, 아니면 클라이언트가 받지 못했는지 판명이 될 테고요.

댓글 다신 분이 지적하셨듯,
클라이언트 쪽의 while 루프의 탈출을 어떻게 할 것인지 매우 심각하게 고민하셔야 합니다.
recv() 로 탈출조건을 만들기는 어렵습니다. 서버가 연결을 끊는다면 몰라도.

코드 적으실 땐

&lt;code&gt;
...
&lt;/code&gt;

OTL

ascpm의 이미지

문제는 사소한데 있었군요..
알다가도 모를.. 암튼 답변 감사드립니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.