2012-06-27 6 views
5

Przede wszystkim, dziękuję wszystkim za przeczytanie tego i pomoc, jestem bardzo wdzięczny.
Po drugie, przepraszam, ale wciąż jestem nowy na tej stronie, a angielski nie jest moim językiem ojczystym, więc mogłem popełnić błędy formatowania i języka. Z góry przepraszam.
Ponadto, moja wiedza C nie jest aż tak dobra, ale chcę się uczyć i ulepszać.
Teraz do sprawy pod ręką:Wysyłanie i odbieranie pliku (serwer/klient) w C przy użyciu gniazda na Unix

Co muszę zrobić jest stworzenie klientem a serwerem, a serwer ma nasłuchiwać połączeń przychodzących.
Następnie mam klienta wysłać dość duży plik tekstowy (wiem, że to tylko JEDEN plik) do serwera.
Serwer wykona następnie operację na pliku (uruchomi skrypt w wysyłanym pliku, który wygeneruje inny plik na wyjściu o nazwie "output.txt"). Serwer następnie będzie musiał wysłać plik output.txt do klienta.

Teraz, mam trochę jak zrobić klienta i serwer (czytałem przewodnik po beeju i kilka innych rzeczy na tej stronie), nawet jeśli prawdopodobnie popełniłem kilka błędów. Potrzebuję pomocy przy odbiorze pliku przez serwer, a następnie wywołaniu skryptu i wysłaniu drugiego pliku do klienta. Na razie to, co zrobiłem, to serwer i klient ... Naprawdę nie wiem, jak iść dalej.
Na marginesie, zrobiłem te pliki przy użyciu tego, co znalazłem na tej stronie i w Internecie, mam nadzieję, że nie są zbyt niechlujne, ponieważ nie jestem tak dobry z programisty.

To client.c

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


#define SOCKET_PORT "50000" 
#define SOCKET_ADR "localhost" 
#define filename "/home/aryan/Desktop/input.txt" 


void error(const char *msg) 
{ 
    perror(msg); 
    exit(0); 
} 


int main() 
{ 
/* Making the client */ 
int sockfd, portno, n; 
struct sockaddr_in serv_addr; 
struct hostent *server; 

char buffer[256]; 

portno = atoi(SOCKET_PORT); 

sockfd = socket(AF_INET, SOCK_STREAM, 0); 
if (sockfd < 0) 
    error("ERROR opening socket"); 

server = gethostbyname(SOCKET_ADR); 

if (server == NULL) 
{ 
    fprintf(stderr,"ERROR, no such host\n"); 
    exit(0); 
} 

bzero((char *) &serv_addr, sizeof(serv_addr)); 
serv_addr.sin_family = AF_INET; 
bcopy((char *)server->h_addr, 
    (char *)&serv_addr.sin_addr.s_addr, 
    server->h_length); 
serv_addr.sin_port = htons(portno); 
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
    error("ERROR connecting"); 

/* Time to send the file */ 
FILE *pf; 
unsigned long fsize; 

pf = fopen(filename, "rb"); 
if (pf == NULL) 
{ 
    printf("File not found!\n"); 
    return 1; 
} 
else 
{ 
    printf("Found file %s\n", filename); 

    fseek(pf, 0, SEEK_END); 
    fsize = ftell(pf); 
    rewind(pf); 

    printf("File contains %ld bytes!\n", fsize); 
    printf("Sending the file now"); 
} 

while (1) 
{ 
    // Read data into buffer. We may not have enough to fill up buffer, so we 
    // store how many bytes were actually read in bytes_read. 
    int bytes_read = fread(buffer, sizeof(char),sizeof(buffer), pf); 
    if (bytes_read == 0) // We're done reading from the file 
     break; 

    if (bytes_read < 0) 
    { 
     error("ERROR reading from file"); 
    } 

    // You need a loop for the write, because not all of the data may be written 
    // in one call; write will return how many bytes were written. p keeps 
    // track of where in the buffer we are, while we decrement bytes_read 
    // to keep track of how many bytes are left to write. 
    void *p = buffer; 
    while (bytes_read > 0) 
    { 
     int bytes_written = write(sockfd, buffer, bytes_read); 
     if (bytes_written <= 0) 
     { 
      error("ERROR writing to socket\n"); 
     } 
     bytes_read -= bytes_written; 
     p += bytes_written; 
    } 
}  

printf("Done Sending the File!\n"); 
printf("Now Closing Connection.\n"); 

fclose(pf); 
close(sockfd); 
return 0; 
} 

To server.c:

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

#define SOCKET_PORT 50000 
#define filename "/home/aryan/Desktop/output.txt" 


void error(const char *msg) 
{ 
    perror(msg); 
    exit(1); 
} 

void* client_thread_proc(void* arg) 
{ 
char buffer[256]; 
struct sockaddr_in serv_addr, cli_addr; 
int n; 
FILE *fp; 

int thisfd = (int)arg; 
printf("Server %d: accepted = %d\n", getpid(), thisfd); 

if (thisfd < 0) 
{ 
    printf("Accept error on server\n"); 
    error("ERROR on accept"); 
    return NULL; 
} 

printf("Connection %d accepted\n", thisfd); 

fp = fopen(filename, "a+b"); 
if (fp == NULL) 
{ 
    printf("File not found!\n"); 
    return NULL; 
} 
else 
{ 
    printf("Found file %s\n", filename); 
} 

/* Time to Receive the File */ 
while (1) 
{ 
    bzero(buffer,256); 
    n = read(thisfd,buffer,255); 
    if (n < 0) error("ERROR reading from socket"); 

    n = fwrite(buffer, sizeof(char), sizeof(buffer), fp); 
    if (n < 0) error("ERROR writing in file"); 

    n = write(thisfd,"I am getting your file...",25); 
    if (n < 0) error("ERROR writing to socket"); 
} /* end child while loop */ 

fclose(fp); 

return NULL; 
} 

void serve_it(int Client) 
{ 
    void* arg = (void*)Client; 
    pthread_t new_thread; 
    pthread_create(&new_thread, NULL, &client_thread_proc, arg); 
} 

/* Making Server */ 
int main() 
{ 
int sockfd, newsockfd, portno; 
socklen_t clilen; 
char buffer[256]; 
struct sockaddr_in serv_addr, cli_addr; 
int n; 
FILE *fp; 

signal (SIGCHLD, SIG_IGN); 

sockfd = socket(AF_INET, SOCK_STREAM, 0); 
if (sockfd < 0) 
    error("ERROR opening socket"); 

bzero((char *) &serv_addr, sizeof(serv_addr)); 

serv_addr.sin_family = AF_INET; 
serv_addr.sin_addr.s_addr = INADDR_ANY; 
serv_addr.sin_port = htons(SOCKET_PORT); 

if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
     error("ERROR on binding"); 

listen(sockfd,5); 

clilen = sizeof(cli_addr); 

while (1) 
{ 
    printf("Server %d accepting connections\n", getpid()); 

    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); 

    serve_it(newsockfd); 
} // serving loop 


close(sockfd); 
return 0; 
} 

Chciałbym kilka wskazówek, w jaki sposób przejść na ...
Jak mogę zrobić skrypt przejdź do pliku, który otrzymałem od klienta do serwera?
Jak wysłać nowy plik z powrotem do tego samego klienta?
A jeśli mógłbyś mi pomóc z błędami w kodzie, byłbym wdzięczny.

Dziękuję wszystkim i przepraszam za długą lekturę. Miłego dnia!

Odpowiedz

5

Pierwszy błąd:

#define filename = "Home\\Desktop\\input.txt" 

powinny być

#define filename "Home\\Desktop\\input.txt" 

Inaczej preprocesor wstawia

= "Home\Desktop\input.txt" 
nie

"Home\\Desktop\\input.txt" 

, którego oczekujesz.

Drugi błąd:

int bytes_read = read(filename /* THAT IS WRONG, FILE HANDLE MUST BE HERE */, buffer, strlen(buffer) /* also WRONG, must be MAX_BYTES_IN_BUFFER or something */); 

Tutaj należy czytać z „PF” (pan otworzył je z fopen() rozmowy) i ostatni argument musi być liczba bajtów, które chcesz przeczytać. Więc jeśli zrobisz strlen (bufor), a bufor zawiera jakieś śmieci na początku środowiska wykonawczego programu, dostaniesz awarię.strlen() musi być wywołany tylko dla prawidłowego łańcucha zakończonego zerem, nie jest to rozmiar tablicy!

EDIT: opracowano pętlę serwera:

while (1) 
{ 
    printf("Server %d accepting connections\n", getpid()); 

    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); 

    serve_it(newsockfd); 
} // serving loop 

The serve_it():

void serve_int(int Client) 
{ 
    void* arg = (void*)Client; 
    pthread_t new_thread; 
    pthread_create(new_thread, NULL, &client_thread_proc, arg); 
} 

void* client_thread(void* arg) 
{ 
    int thisfd = (int)arg; 
    printf("Server %d: accepted = %d\n", getpid(), thisfd); 

    if (thisfd < 0) 
    { 
     printf("Accept error on server\n"); 
     error("ERROR on accept"); 
     return NULL; 
    } 

    printf("Connection %d accepted\n", thisfd); 

    fp = fopen(filename, "a+b"); 
    if (fp == NULL) 
    { 
     printf("File not found!\n"); 
     return NULL; 
    } 
    else 
    { 
     printf("Found file %s\n", filename); 
    } 

    /* Time to Receive the File */ 
    while (1) 
    { 
     bzero(buffer,256); 
     n = read(thisfd,buffer,255); 
     if (n < 0) error("ERROR reading from socket"); 

     n = fwrite(buffer, sizeof(buffer), 1, fp); 
     if (n < 0) error("ERROR writing in file"); 

     n = write(thisfd,"I am getting your file...",25); 
     if (n < 0) error("ERROR writing to socket"); 
    } /* end child while loop */ 

    return NULL; 
} 
+0

Mmmm podczas dodawania odpowiedź Ci trochę powielane na server.c ... mogłaś się to jasne? gubię się w tym, co zatrzymać, a czego nie zatrzymać ... a moja głowa eksploduje. – AscaL

+0

Po prostu chodzi o to, że client_thread_proc jest powtarzany dwa razy, jeden w głównej() i jeden jako deklaracja funkcji (jeśli rozumiesz to poprawnie, i to jest duże, jeśli). ale jeśli jest to funkcja, dlaczego nie nazwać tego po prostu? a jeśli nie, dlaczego deklarujesz to 2 razy? Zgubiłem się: P – AscaL

+0

C nie jest pytonem, usunąłem wątek_proc z głównego() –