انجمن‌های فارسی اوبونتو

لطفاً به انجمن‌ها وارد شده و یا جهت ورود ثبت‌نام نمائید

لطفاً جهت ورود نام کاربری و رمز عبورتان را وارد نمائید


توزیع گنو/لینوکس اوبونتو ۲۰ ساله شد 🎉

نویسنده موضوع: مشکل با برنامه نویسی سوکت در زبان C  (دفعات بازدید: 3306 بار)

0 کاربر و 1 مهمان درحال مشاهده موضوع.

آفلاین دانیال بهزادی

  • ناظر انجمن
  • *
  • ارسال: 19722
  • جنسیت : پسر
  • Urahara Kiesuke
    • وبلاگ
با سلام خدمت دوستان گرامی. برای انجام پروژه درس آزمایشگاه معماری مجبور شدم برنامه ای بنویسم که فایل رو در شبکه به کامپیوتر دیگه ای بفرسته. البته سواد زیادی در زمینه برنامه نویسی شبکه ندارم و با کلی راهنما خوندن تونستم این برنامه رو بنویسم که محتویات فایل client.txt (که قبل از اجرای برنامه در مسیر خود برنامه قرار داره) رو بخونه و اون رو در server.txt (که خود برنامه در مسیرش ایجاد می کنه) بنویسه.برای شروع هم شبکه localhost خود کامپوتر رو قرار دادم که احتمالا می شه عوضش کرد.
این برنامه اتصال رو برقرار می کنه و بعد از اون در حلقه whille در server.c گیر می کنه. نظر خودم اینه که احتمالا EndOfFile رو تشخیص نمی ده. ممنون می شم اگه دوستان نگاهی بهش بندازن و ببینن مشکلش چیه. اگه هم برنامه ی بهتری سراغ دارید خیلی خوشحال می شم اگه معرفیش کنید.
این هم سورس ها:

server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
 
#define PORT 2080
 
main()
{
int sock1,sock2, clength;
sock1 =  socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in serv,cli;
 
serv.sin_family = AF_INET;
serv.sin_port = htons(PORT);
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(sock1,(struct sockaddr *)&serv, sizeof(serv));
listen(sock1,5);
clength = sizeof(cli);
int i=0;
char buf[50];
sock2 = accept(sock1,(struct sockaddr *)&cli,(socklen_t*)&clength);
printf("\n Client Connected\n");
FILE* fp = fopen("server.txt","w");
while(!feof(fp)){
/*bzero(buf,sizeof(buf));*/
fread(buf,sizeof(char),50,fp);
write(sock2,buf,50);
if (buf=='\0')
break;
}
write(sock2,"quit1234",50);
fclose(fp);
return 0;
}

و

client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
 
#define PORT 2080
 
main()
{
int sock1;
sock1 =  socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in serv;
 
serv.sin_port = htons(PORT);
printf("%x %x\n",PORT,htons(PORT));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
printf("client connecting\n");
connect(sock1, (struct sockaddr *)&serv,sizeof(serv));
char buf[50];
FILE* fp = fopen("client.txt","r");
while(1){
/*bzero(buf,sizeof(buf));*/
read(sock1,buf,50);
if(strcmp(buf,"quit1234")==0)
{
break;
}
fprintf(fp,"%s",buf);
}
fclose(fp);
}
اگه این ارسال بهت کمک کرد، دنبال دکمهٔ تشکر نگرد. به جاش تو هم به جامعهٔ آزادت کمک کن

آفلاین HojjatJafary

  • Full Member
  • *
  • ارسال: 107
پاسخ به: مشکل با برنامه نویسی سوکت در زبان C
« پاسخ #1 : 23 آذر 1389، 02:18 ق‌ظ »
سلام

محتویات فایل client.txt (که قبل از اجرای برنامه در مسیر خود برنامه قرار داره) رو بخونه و اون رو در server.txt (که خود برنامه در مسیرش ایجاد می کنه) بنویسه
نمی دانم در موقع ایجاد پست اشتباه کرده اید یا در موقع نوشتن کد. چون اگر قرار است محتویات client.txt خوانده شود چرا در فایل client.c فایل را به صورت فقط خواندنی باز کرده اید و سپس روی آن می نویسید!

اگر قرار است سرور اطلاعات فرستاده شده از کلاینت را بگیرد و روی server.txt بنویسد چرا شما این فایل را می خوانید و روی سوکت می نویسید؟

موضوع خیلی گیج کننده شد!؟ کی قراره بخونه کی قراره بنویسه؟ کی به کی قراره اطلاعات بفرسته؟

شاید این بتواند کمکتان کند: http://www.linuxhowtos.org/C_C++/socket.htm

آفلاین Blossom

  • Full Member
  • *
  • ارسال: 129
    • سار
پاسخ به: مشکل با برنامه نویسی سوکت در زبان C
« پاسخ #2 : 23 آذر 1389، 09:10 ق‌ظ »
من امروز سر وقت روی این کار می‌کنم. ولی خب فعلن این رو ببین، بهترین مرجع برنامه‌نویسی شبکست :D
http://beej.us/guide/bgnet/

آفلاین Blossom

  • Full Member
  • *
  • ارسال: 129
    • سار
پاسخ به: مشکل با برنامه نویسی سوکت در زبان C
« پاسخ #3 : 24 آذر 1389، 06:56 ب‌ظ »
با سلام خدمت دوستان گرامی. برای انجام پروژه درس آزمایشگاه معماری مجبور شدم برنامه ای بنویسم که فایل رو در شبکه به کامپیوتر دیگه ای بفرسته. البته سواد زیادی در زمینه برنامه نویسی شبکه ندارم و با کلی راهنما خوندن تونستم این برنامه رو بنویسم که محتویات فایل client.txt (که قبل از اجرای برنامه در مسیر خود برنامه قرار داره) رو بخونه و اون رو در server.txt (که خود برنامه در مسیرش ایجاد می کنه) بنویسه.برای شروع هم شبکه localhost خود کامپوتر رو قرار دادم که احتمالا می شه عوضش کرد.
این برنامه اتصال رو برقرار می کنه و بعد از اون در حلقه whille در server.c گیر می کنه. نظر خودم اینه که احتمالا EndOfFile رو تشخیص نمی ده. ممنون می شم اگه دوستان نگاهی بهش بندازن و ببینن مشکلش چیه. اگه هم برنامه ی بهتری سراغ دارید خیلی خوشحال می شم اگه معرفیش کنید.
این هم سورس ها:

server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
 
#define PORT 2080
 
main()
{
int sock1,sock2, clength;
sock1 =  socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in serv,cli;
 
serv.sin_family = AF_INET;
serv.sin_port = htons(PORT);
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(sock1,(struct sockaddr *)&serv, sizeof(serv));
listen(sock1,5);
clength = sizeof(cli);
int i=0;
char buf[50];
sock2 = accept(sock1,(struct sockaddr *)&cli,(socklen_t*)&clength);
printf("\n Client Connected\n");
FILE* fp = fopen("server.txt","w");
while(!feof(fp)){
/*bzero(buf,sizeof(buf));*/
fread(buf,sizeof(char),50,fp);
write(sock2,buf,50);
if (buf=='\0')
break;
}
write(sock2,"quit1234",50);
fclose(fp);
return 0;
}

و

client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
 
#define PORT 2080
 
main()
{
int sock1;
sock1 =  socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in serv;
 
serv.sin_port = htons(PORT);
printf("%x %x\n",PORT,htons(PORT));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
printf("client connecting\n");
connect(sock1, (struct sockaddr *)&serv,sizeof(serv));
char buf[50];
FILE* fp = fopen("client.txt","r");
while(1){
/*bzero(buf,sizeof(buf));*/
read(sock1,buf,50);
if(strcmp(buf,"quit1234")==0)
{
break;
}
fprintf(fp,"%s",buf);
}
fclose(fp);
}
آقا من این رو پیاده کردم. البته اگر درست متوجه شده باشم شما می‌خواستی که سرور یک فایل رو ارسال کنه و من با همین ذهنیت نوشتم. البته همین اول کپی‌رایت رو رعایت کنم که من سرور آقای beejs رو به عنوان سمپل کد انگولک کردم و به این رسیدم. پس راهنمای ایشون هم می‌تونه مفسر کد باشه:

/*
 ** server.c -- a stream socket server and file sender ;)
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>

#define PORT "3490"  // the port users will be connecting to

#define BACKLOG 10     // how many pending connections queue will hold

#define MAXDATASIZE 1024 //max number of bytes we can get at once from file

void sigchld_handler(int s) {
    while (waitpid(-1, NULL, WNOHANG) > 0);
}

// get sockaddr, IPv4 or IPv6:

void *get_in_addr(struct sockaddr *sa) {
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*) sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*) sa)->sin6_addr);
}

int main(int argc, char * argv[]) {
    int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
    struct addrinfo hints, *servinfo, *p;
    struct sockaddr_storage their_addr; // connector's address information
    socklen_t sin_size;
    struct sigaction sa;
    int yes = 1;
    char s[INET6_ADDRSTRLEN];
    int rv;
    FILE *ifp; //input file pointer

    char buf[MAXDATASIZE]; //buffer for input file

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; // use my IP

    if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    // loop through all the results and bind to the first we can
    for (p = servinfo; p != NULL; p = p->ai_next) {
        if ((sockfd = socket(p->ai_family, p->ai_socktype,
                p->ai_protocol)) == -1) {
            perror("server: socket");
            continue;
        }

        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
                sizeof (int)) == -1) {
            perror("setsockopt");
            exit(1);
        }

        if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            perror("server: bind");
            continue;
        }

        break;
    }

    if (p == NULL) {
        fprintf(stderr, "server: failed to bind\n");
        return 2;
    }

    freeaddrinfo(servinfo); // all done with this structure

    if (listen(sockfd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }

    sa.sa_handler = sigchld_handler; // reap all dead processes
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    if (sigaction(SIGCHLD, &sa, NULL) == -1) {
        perror("sigaction");
        exit(1);
    }

    printf("server: waiting for connections...\n");

    while (1) { // main accept() loop
        sin_size = sizeof their_addr;
        new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &sin_size);
        if (new_fd == -1) {
            perror("accept");
            continue;
        }

        inet_ntop(their_addr.ss_family,
                get_in_addr((struct sockaddr *) &their_addr),
                s, sizeof s);
        printf("server: got connection from %s\n", s);

        if (!fork()) { // this is the child process
            close(sockfd); // child doesn't need the listener
            ifp = (argc > 1) ? fopen(*++argv, "r") : stdin;
            if (ifp == NULL) {
                ifp = stdin;
            }
            while (fgets(buf, MAXDATASIZE, ifp))
                if (send(new_fd, buf, strlen(buf), 0) == -1)
                    perror("send");
            close(new_fd);
            exit(0);
        }
        close(new_fd); // parent doesn't need this
    }

    return 0;
}
/*
 ** client.c -- a stream socket client and file receiver
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

#include <arpa/inet.h>

#define PORT "3490" // the port client will be connecting to

#define MAXDATASIZE 1024 // max number of bytes we can get at once

// get sockaddr, IPv4 or IPv6:

void *get_in_addr(struct sockaddr *sa) {
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*) sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*) sa)->sin6_addr);
}

int main(int argc, char *argv[]) {
    int sockfd, numbytes;
    char buf[MAXDATASIZE];
    struct addrinfo hints, *servinfo, *p;
    int rv;
    char s[INET6_ADDRSTRLEN];
    FILE *ofp;
    if (argc < 2) {
        fprintf(stderr, "usage: client hostname [file name]\n");
        exit(1);
    }
    ofp = (argc > 2) ? fopen(argv[2], "w") : stdout;
    if (ofp == NULL)
        ofp = stderr;
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    // loop through all the results and connect to the first we can
    for (p = servinfo; p != NULL; p = p->ai_next) {
        if ((sockfd = socket(p->ai_family, p->ai_socktype,
                p->ai_protocol)) == -1) {
            perror("client: socket");
            continue;
        }

        if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            perror("client: connect");
            continue;
        }

        break;
    }

    if (p == NULL) {
        fprintf(stderr, "client: failed to connect\n");
        return 2;
    }

    inet_ntop(p->ai_family, get_in_addr((struct sockaddr *) p->ai_addr),
            s, sizeof s); //Convert IP addresses to human-readable form
    printf("client: connecting to %s\n", s);

    freeaddrinfo(servinfo); // all done with this structure

    while ((numbytes = recv(sockfd, buf, MAXDATASIZE - 1, 0)) > 0) {
        buf[numbytes] = '\0';

        if (fputs(buf, ofp) == EOF) {
            perror("fputs");
            break;
        }
    }



    close(sockfd);

    return 0;
}
برای کامپایل هم که بدیهیه:
gcc server.c -o server
gcc client.c -o client
و برای اجرای سرور:
./server inputfile.txt
و برای اجرای کلاینت:
./client 127.0.0.1 outfile.txt
or
./client localhost outfile.txt
و بد نیست چک کنیم ببینیم فایل منتقل شده یکی هست یا نه :D

md5sum inputfile.txt outputfile.txt
البته جای توضیح هم هست که این برنامه فایل‌های متنی رو انتقال می‌ده و برای انتقال فایل‌های باینری، باید متد‌های خوندن و نوشتن از (به) فایل تغییر کنه که اونم کار سختی نیست.