소켓 select 뭐가 문제일까요?

gag2012의 이미지

서버코드입니다.

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
 
#define SERV_TCP_PORT 
#define SERV_ADDR ""
 
void transfile(int s2);
void receivefile(int s2);
 
void main(){
   int s1,s2, x, y;
   struct sockaddr_in serv_addr, cli_addr;
   char buf[50];
   socklen_t  xx;
   printf("Hi, I am the server\n");
 
   bzero((char *)&serv_addr, sizeof(serv_addr));
   serv_addr.sin_family=PF_INET;
   serv_addr.sin_addr.s_addr=inet_addr(SERV_ADDR);
   serv_addr.sin_port=htons(SERV_TCP_PORT);
 
   //open a tcp socket
   if ((s1=socket(PF_INET, SOCK_STREAM, 0))<0){
      printf("socket creation error\n");
      exit(1);
   }
 
   // bind ip
 
   x =bind(s1, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
   if (x < 0){
      printf("binding failed\n");
      exit(1);
   }
   printf("binding passed\n");
   listen(s1, 5);
   xx = sizeof(cli_addr);
   int i,k,f;
   char doit[50];
   char str[50];
 
  for(i; i<3; i++){
     s2 = accept(s1, (struct sockaddr *)&cli_addr, &xx);
     printf("we passed accept. new socket num is %d\n", s2);
 
     k = fork();
 
     if(k==0){
        printf("now connect with client %d \n", s2);
        printf("========================\n");
        y = read(s2, buf, 50);
        buf[y]=0;
        if(strcmp(buf, "hello")==0) {
           printf("successfull connect!\n");
           write(s2, "Type <download> or <upload>", 27);
           y= read(s2, doit, 50);
           doit[y] = 0;
           if(strcmp(doit, "download")==0) transfile(s2);
           else if(strcmp(doit, "upload")==0) receivefile(s2);
        }
        close(s2);
        close(s1);
        exit(0);
     }  //child do
     else {
        close(s2);
     }  //parent do
  }
  close(s1);   // close the original socket
}

receivefile()함수입니다.

void receivefile(int s2){
   struct timeval timeout;
   int x, y, cnt, rv;
   char fileName[50];
   char content[60];
   fd_set rset, temp;
   FD_ZERO(&rset);
   FD_ZERO(&temp);
   FD_SET(s2, &rset);
   timeout.tv_sec = 3;
   timeout.tv_usec = 0;
 
   printf("receivefile_mode\n");
   write(s2, "which file you want?", 20);
   y = read(s2, fileName, 50);
   fileName[y] = 0;
   printf("client : %s\n", fileName);
   x = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 00777);
   if (x<0){
     write(s2, "protocol error", 20);
     close(y);
     return;
   }
 
   for(cnt; cnt<20; cnt++){
     printf("!!!!이 부분이 출력되지 않습니다!!!!\n");
     FD_SET(s2, &rset);
     temp = rset;
 
    /* upload */
     rv = select(s2+1, &temp, NULL, NULL, &timeout);
     if(rv==-1){
        perror("select");
     }
     else if(rv==0){
        break;
     }
     else {
        if(FD_ISSET(s2, &temp)){
          y = read(s2, content, 50);
          content[y] = 0;
          write(1, content, y);
          write(x, content, y);
        }
      }
   }
   printf("\n socket : %s done\n", s2);
}

클라이언트는 윈도우 비주얼스튜디오에서 진행했습니다.

#include "winsock2.h"
#include "ws2tcpip.h"
#include "stdio.h"
#pragma warning (disable : 4996)
#define SERVER_PORT 24680  // server port number
#define BUF_SIZE 4096 // block transfer size  
#define QUEUE_SIZE 10
#define IPAddress "165.246.38.151" // server IP address
 
void download(int s, int n, char buf[]);
void upload(int s, int n, char buf[]);
 
int main()
{
	WORD		        wVersionRequested;
	WSADATA		wsaData;
	SOCKADDR_IN          target; //Socket address information
	SOCKET		        s;
	int			err;
	int			bytesSent;
	char		        buf[100];
 
	//--- INITIALIZATION -----------------------------------
	wVersionRequested = MAKEWORD(1, 1);
	err = WSAStartup(wVersionRequested, &wsaData);
 
	if (err != 0) {
		printf("WSAStartup error %ld", WSAGetLastError());
		WSACleanup();
		return false;
	}
	//------------------------------------------------------
 
	//---- Build address structure to bind to socket.--------  
	target.sin_family = AF_INET; // address family Internet
	target.sin_port = htons(SERVER_PORT); //Port to connect on
	inet_pton(AF_INET, IPAddress, &(target.sin_addr.s_addr)); // target IP
															  //--------------------------------------------------------
 
 
															  // ---- create SOCKET--------------------------------------
	s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket
	if (s == INVALID_SOCKET)
	{
		printf("socket error %ld", WSAGetLastError());
		WSACleanup();
		return false; //Couldn't create the socket
	}
	//---------------------------------------------------------
 
 
	//---- try CONNECT -----------------------------------------
	if (connect(s, (SOCKADDR *)&target, sizeof(target)) == SOCKET_ERROR)
	{
		printf("connect error %ld", WSAGetLastError());
		WSACleanup();
		return false; //Couldn't connect
	}
 
	//protocol test
	send(s, "hello", 5, 0);
 
	//recieve bytes from server
	int n;
	n = recv(s, buf, 50, 0);
	buf[n] = 0; // make a string
	printf("%s\n", buf);
 
	//---- SEND bytes -------------------------------------------
	gets_s(buf, 99);
	send(s, buf, strlen(buf), 0); // use "send" in windows
 
	if (strcmp(buf, "download") == 0) download(s, n, buf);
	else if (strcmp(buf, "upload") == 0) upload(s, n, buf);
	else {
		printf("protocol error");
		bytesSent = send(s, "protocol error try again", 20, 0);
	}
 
	//--------------------------------------------------------
	closesocket(s);
	WSACleanup();
 
	return 0;
}

업로드하는 코드입니다.

윈도우(클라이언트)에서 리눅스(서버)에다가 자신의 파일을 업로드할 수 있게끔 만들었습니다.

그런데 서버에 파일은 생성되지만 내용물은 써지지 않습니다.

질문1 ) select함수로 윈도우가 send()하는 것을 인식하여 위 코드가 작동할 수 있을까요?

질문2 ) receivefile()함수에서 printf가 왜 출력되지 않을까요? for문을 아에 안들어가는 것 같습니다ㅠ

허접한 질문 죄송합니다

( _ _ )

m4170의 이미지

루프 카운트의 초기화를 확인해봐야 할 것으로 보입니다.

 int x, y, cnt, rv;

for(cnt; cnt<20; cnt++){

cnt가 초기화 되지 않으면 어떻게 되는지 확인이 필요할 것으로 보입니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.