2010-10-10 33 views
0

從tcp套接字發送和接收文件。發送文件可以工作,但試圖保存文件不起作用。試圖通過套接字接收文件

#include <cassert> 
#include <arpa/inet.h> 
#include <cstdlib> 
#include <iostream> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <errno.h> 
#include <string.h> 
#include <fstream> 
#include <time.h> 
#include <strings.h> 
#include <sstream> 
#include <vector> 
#include <netdb.h> 
#include <netinet/in.h> 
#include <sys/sendfile.h> 
#include <fcntl.h> 

using namespace std; 
using std::endl; 

int newscount = 0; 
int doccount = 0; 
int photocount = 0; 
int johns = 0; 
vector<string> newsvector; 
vector<string> photosvector; 
vector<string> docsvector; 

void serverlogs(const char*msg) /* writing to log file */ 
{ 

time_t rawtime; 
struct tm * timeinfo; 
time (&rawtime); 
timeinfo = localtime(&rawtime); 


ofstream file; 
file.open("serverlog.txt",ios::app); 
if (file.is_open()) 
{file<<msg; 
file<<" @ "; 
file<<asctime(timeinfo); 
file<<"\n"; 
file.close(); 
return; 
} 
else 
cout<<"Error Creating log file"; 
return; 
} 

void clientlogs(const char*msg) /* writing to log file */ 
{ 
time_t rawtime; 
struct tm * timeinfo; 
time (&rawtime); 
timeinfo = localtime(&rawtime); 
ofstream file; 
file.open("clientlog.txt",ios::app); 
if (file.is_open()) 
{file<<msg; 
file<<" @ "; 
file<<asctime(timeinfo); 
file<<"\n"; 
file.close(); 
return; 
} 
else 
cout<<"Error Creating log file"; 
return; 
} 
void error(const char*msg) /* If there is an error exit the program with err# 1 */ 
{ 
perror(msg); 
exit(1); 
} 

void publishdocsvector(const char*msg) 
{ 
    docsvector.push_back(msg); 
    ofstream file; 
    file.open("docfiles.txt",ios::app); 
    if (file.is_open()) 
    { 
    for(int j = 0; j < docsvector.size() ;j++) 
    {file<<docsvector[j];} 
    file.close(); 
    } 
else 
cout<<"Error creating news archive"; 
return; 
} 
void publishphotosvector(const char*msg) 
{ 
    photosvector.push_back(msg);  
    ofstream file; 
    file.open("photofiles.txt",ios::app); 
    if (file.is_open()) 
    { 
    for(int j = 0; j < photosvector.size() ;j++) 
    {file<<photosvector[j];} 
    file.close(); 
    } 
else 
cout<<"Error creating news archive"; 
return; 
} 
void publishnewsvector(const char*msg) 
{ 
    newsvector.push_back(msg); 
    ofstream file; 
    file.open("newsfiles.txt",ios::app); 
    if (file.is_open()) 
    { 
    for(int j = 0; j < newsvector.size() ;j++) 
    {file<<newsvector[j];} 
    file.close(); 
    } 
else 
cout<<"Error creating news archive"; 
return; 
} 

void sendfile(const char*msg) 
{ 
// to be implemented later//  
} 


int main (int argc, char*argv[]) /*Main Program accepting a port number and something  else for arguments */ 
{ 

int sockfd, newsockfd, portno, clilen, n,test; 
string publish="publish"; 
string search= "search"; 
string get="get"; 
string newsstring = "news"; 
string docstring = "doc"; 
string photostring = "photo"; 
string wrap = "exit"; 
char buffer[256]; 
char seats [50]; 
serverlogs("Server Running"); 
struct sockaddr_in serv_addr, cli_addr; /* Defines the server address and client address and types of structures with the same format as socket address */ 
if (argc < 2) 
{ 
    fprintf(stderr,"Please provide a port number next time plz, goodbye!"); 
    exit(1); 
} 
sockfd = socket(AF_INET, SOCK_STREAM, 0); /* If Sock_Dgram then then it will open a udp socket */ 
if (sockfd < 0) 
error("Error opening socket"); 
bzero((char *)&serv_addr, sizeof(serv_addr)); /* sets the server address to zero usings its reference */ 
portno = atoi(argv[1]); /*2nd argument vector is the port number and converted into an integer, the first [0] is the running program */ 
serv_addr.sin_family = AF_INET; /* The structure sockaddr_in has four fields, this is first one and should always be this */ 
serv_addr.sin_port = htons(portno); /* convert port number into network byte order */ 
serv_addr.sin_addr.s_addr = INADDR_ANY; /*3rd Field uses Ip address of host machine */ 
if (bind(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr))<0) /*bind socket to sockfd and address of server ,and needs size of address need struct of sockaddr, see bind man for details*/ 
    error("Couldn't bind socket to address"); 
listen(sockfd,5); 
clilen = sizeof(cli_addr); 
serverlogs("going into server loop"); 
int pid = fork(); 
if (pid < 0) 
    serverlogs("error on initial separtion of server and client"); 
if (pid==0) 
{ 
// server loop later on this will be the child process and client will be main 
while (1) 
{ /* Server loop loop*/ 
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, (socklen_t*)&clilen); 
if (newsockfd < 0) 
    /* error("Corrupt log"); */ 
    serverlogs("Connection not accepted"); 
else (newsockfd > 0); 
int ppID = fork(); 
if (ppID < 0) 
    serverlogs("A new server process failed to be created"); 
if (ppID == 0) 
{ 

    int uid; 
    uid = johns; 

printf("A new client connected with identity: %d\n", getpid()); 
close(sockfd); 
serverlogs("A john Connected to the server"); 
printf("my unique id: %d\n", uid); 
serverlogs(seats); 
bzero(buffer,256); 
//n = write(newsockfd,"Each client is a 'john' \n",26); 
/* This loop read from socket and writes to other persons sockets */ 
    while(1) 
    { 
    bzero(buffer,256); 
    n = read(newsockfd,buffer,256); 
    if (n < 0) 
     printf ("error reading from socket here is the message: %s",buffer); 
     if (publish[0] == buffer[0]) 
      { 
       n = write(newsockfd,"What category are you publishing in?(news,photos,documents) \n",62); 
       bzero(buffer,256); 
       n = read(newsockfd,buffer,256); 
       if(buffer[0]==newsstring[0]) 
       { 
        n = write(newsockfd,"Type the name of the file to publish and wait 10 seconds \n",59); 
        bzero(buffer,256); 
        n = read(newsockfd,buffer,256); 
        publishnewsvector(buffer); 
        serverlogs(seats); 
        serverlogs("client is trying to publish a news file:"); 
        serverlogs(buffer); 
        /*start recieving a file*/ 
        std::ofstream file; 
        file.open(buffer, std::ios::out | std::ios::binary); 
        assert(file.is_open()); 
        while (1) { 
        std::cout << ".."; 
        bzero(buffer,256); 
        n = read(newsockfd, buffer, sizeof(buffer)); 
        assert(n != -1); 
        if (n == 0) 
        break; 
        file.write(buffer, n); 
        i++; 
           } 
        file.close(); 
        serverlogs("File Transfered successfully"); 

       } 
       if(buffer[0]==docstring[0]) 
       { 
        n = write(newsockfd,"Type the name of the file to publish \n",39); 
        bzero(buffer,256); 
        n = read(newsockfd,buffer,256); 
        publishdocsvector(buffer); 
        serverlogs(seats); 
        serverlogs("client is tyring to publish a document:"); 
        serverlogs(buffer); 
        /*start recieving a file*/ 

        std::ofstream file; 
        file.open(buffer, std::ios::out | std::ios::binary); 
        assert(file.is_open()); 
        while (1) { 
        std::cout << "."; 
        bzero(buffer,256); 
        n = read(newsockfd, buffer, sizeof(buffer)); 
        assert(n != -1); 
        if (n == 0) 
        break; 
        file.write(buffer, n); 
           } 
        file.close(); 
        serverlogs("File Transfered successfully"); 

       } 
       if(buffer[0]==photostring[0]) 
       { 
        n = write(newsockfd,"Type the name of the file to publish \n",39); 
        bzero(buffer,256); 
        n = read(newsockfd,buffer,256); 
        publishphotosvector(buffer); 
        serverlogs(seats); 
        serverlogs("client is trying to publish photo file:"); 
        serverlogs(buffer); 
        /*start recieving a file*/ 
        std::ofstream file; 
        file.open(buffer, std::ios::out | std::ios::binary); 
        assert(file.is_open()); 
        while (1) { 
        std::cout << "."; 
        bzero(buffer,256); 
        n = read(newsockfd, buffer, sizeof(buffer)); 
        assert(n != -1); 
        if (n == 0) 
        break; 
        file.write(buffer, n); 
           } 
        file.close(); 
        serverlogs("File Transfered successfully"); 
       } 

      } 
     if (get[0] ==buffer[0]) 
      { 
       n = write(newsockfd,"\n What file do you want to get? \n",35); 
       bzero(buffer,256); 
       n = read(newsockfd,buffer,256); 
       serverlogs(seats); 
       serverlogs("client wants file:"); 
       serverlogs(buffer); 
       //** start sending the file**// 
        FILE* searchfile = 0; 
        long Size = 0; 
        searchfile = fopen(buffer,"r"); 
        fseek(searchfile, 0, SEEK_END); 
        Size = ftell(searchfile); 
        char *bufferfile = (char*)malloc(Size); 
        memset(bufferfile, 0, Size); 
        fseek(searchfile, 0, SEEK_SET); 
        fread(bufferfile, Size, 1, searchfile); 
        n = write(newsockfd,bufferfile,256); 
        fclose(searchfile); 
       serverlogs("Sent the file to the client"); 
       serverlogs(seats); 

      } 


     if (search[0] == buffer[0]) 
      { 
      bzero(buffer,256); 
      n = write(newsockfd,"What category are you searching? \n",35); 
      bzero(buffer,256); 
      n = read(newsockfd,buffer,256); 
      serverlogs(seats); 
      serverlogs("client searching for"); 
      serverlogs(buffer); 
      if(buffer[0]==newsstring[0]) 
       { 
        FILE* searchfile = 0; 
        long Size = 0; 
        searchfile = fopen("newsfiles.txt","r"); 
        fseek(searchfile, 0, SEEK_END); 
        Size = ftell(searchfile); 
        char *bufferfile = (char*)malloc(Size); 
        memset(bufferfile, 0, Size); 
        fseek(searchfile, 0, SEEK_SET); 
        fread(bufferfile, Size, 1, searchfile); 
        n = write(newsockfd,bufferfile,256); 
        fclose(searchfile); 
       } 
      if(buffer[0]==docstring[0]) 
       { 

        FILE* searchfile = 0; 
        long Size = 0; 
        searchfile = fopen("docfiles.txt","r"); 
        fseek(searchfile, 0, SEEK_END); 
        Size = ftell(searchfile); 
        char *bufferfile = (char*)malloc(Size); 
        memset(bufferfile, 0, Size); 
        fseek(searchfile, 0, SEEK_SET); 
        fread(bufferfile, Size, 1, searchfile); 
        n = write(newsockfd,bufferfile,256); 
        fclose(searchfile); 
       } 
      if(buffer[0]==photostring[0]) 
       { 
        FILE* searchfile = 0; 
        long Size = 0; 
        searchfile = fopen("photofiles.txt","r"); 
        fseek(searchfile, 0, SEEK_END); 
        Size = ftell(searchfile); 
        char *bufferfile = (char*)malloc(Size); 
        memset(bufferfile, 0, Size); 
        fseek(searchfile, 0, SEEK_SET); 
        fread(bufferfile, Size, 1, searchfile); 
        n = write(newsockfd,bufferfile,256); 
        fclose(searchfile); 
       } 
      } 
     if(buffer[0]==wrap[0]) 
      { 
       close(sockfd); 
       close(newsockfd); 
       johns = johns - 1; 
       serverlogs("A john left"); 
       return 0; 
      } 
    n = write(newsockfd,"\n Waiting for a command I can understand:(publish,search,get,exit)",66); 

    } /* while loop to listen to commands from client bracket */ 
}/*what to do when client connected*/ 


} /*Creating child/zombies */ 
} /* division between client and server*/ 
else 
{ 
    while (1) 

    {int ssockfd, pportno, p,peer; 
    struct sockaddr_in peer_addr; 
    struct hostent *peerserver; 
    char bbuffer[256]; 
    printf ("%s \n", "Welcome to the Social"); 
    printf ("%s \n", "Please type the port number of the server \n"); 
    cin>>pportno; 
    ssockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) 
    error("ERROR opening socket Please try again"); 
    printf ("%s \n", "Please type in the hostname of client ie sunlab1.njit.edu \n"); 
    char peers[256]; 
    cin >> peers; 
    peerserver = gethostbyname(peers); 
    if (peerserver == NULL) 
    { 
    fprintf(stderr,"could not connect to ip address"); 
    peerserver = gethostbyname((const char*)peer); 
    if (peerserver == NULL) 
    fprintf(stderr,"still null"); 
    exit(0); 
    } 
    bzero((char *) &peer_addr, sizeof(peer_addr)); 
    peer_addr.sin_family = AF_INET; 
    bcopy((char *)peerserver->h_addr,(char *)&peer_addr.sin_addr.s_addr,peerserver->h_length); 
    peer_addr.sin_port = htons(pportno); 
    if (connect(ssockfd,(struct sockaddr *)&peer_addr,sizeof(peer_addr)) < 0) 
    error("ERROR connecting"); 
    clientlogs("Connected to peer"); 
    clientlogs((const char*)&peer); 
    printf("Please enter a command, publish,search or get: "); 
    while (1) 
    { 
    bzero(bbuffer,256); 
    fgets(bbuffer,255,stdin); 
    char apub[] = "publish"; 
    char asearch[] = "search"; 
    char aget[]="get"; 
     if (bbuffer[0]==apub[0] && bbuffer[1]==apub[1]) 
      { 
       p = write(ssockfd,bbuffer,strlen(bbuffer)); 
       if (p < 0) 
       error("ERROR writing to socket"); 
       bzero(bbuffer,256); 
       p = read(ssockfd,bbuffer,255); 
       if (p < 0) 
       error("ERROR reading from socket"); 
       printf("%s",bbuffer); //What category are you publishing in// 
       bzero(bbuffer,256); 
       fgets(bbuffer,255,stdin); 
       p = write(ssockfd,bbuffer,strlen(bbuffer)); 
       clientlogs("Client publishing"); 
       clientlogs(bbuffer); 
       if (p < 0) 
       error("ERROR writing to socket"); 
       bzero(bbuffer,256); 
       p = read(ssockfd,bbuffer,255); 
       if (p < 0) 
       error("ERROR reading from socket"); 
       printf("%s",bbuffer); //Type the name of the file// 
       fgets(bbuffer,255,stdin); 
       p = write(ssockfd,bbuffer,strlen(bbuffer)); 
       clientlogs(bbuffer); 
       FILE* searchfile = 0; 
       long Size = 0; 
       searchfile = fopen(bbuffer,"r"); 
       fseek(searchfile, 0, SEEK_END); 
       Size = ftell(searchfile); 
       char *bufferfile = (char*)malloc(Size); 
       memset(bufferfile, 0, Size); 
       fseek(searchfile, 0, SEEK_SET); 
       fread(bufferfile, Size, 1, searchfile); 
       p = write(ssockfd,bufferfile,256); 
       fclose(searchfile); 


       } 

     if(bbuffer[0]==aget[0] && bbuffer[1]==aget[1]) 
     {  
       p = write(ssockfd,bbuffer,strlen(bbuffer)); 
       if (p < 0) 
       error("ERROR writing to socket"); 
       bzero(bbuffer,256); 
       p = read(ssockfd,bbuffer,255); 
       if (p < 0) 
       error("ERROR reading from socket"); 
       printf("%s",bbuffer); //What file do you want to get? // 
       bzero(bbuffer,256); 
       fgets(bbuffer,255,stdin); 

       p = write(ssockfd,bbuffer,strlen(bbuffer)); 
       if (p < 0) 
       error("ERROR writing to socket"); 
       clientlogs("client wants file:"); 
       clientlogs(bbuffer); 
       /*start recieving a file*/ 

       std::ofstream file; 
       file.open(bbuffer, std::ios::out | std::ios::binary); 
       assert(file.is_open()); 
       char buffer[255]; 
       while (1) { 
       std::cout << "."; 
       bzero(bbuffer,256); 
       p = read(ssockfd, bbuffer, sizeof(bbuffer)); 
       assert(p != -1); 
       if (p == 0) 
       break; 
       file.write(bbuffer, p); 
          } 
       file.close(); 
       serverlogs("File Transfered successfully"); 
      } 

     if (bbuffer[0]==asearch[0] && bbuffer[1]==asearch[1]) 
     { 
       p = write(ssockfd,bbuffer,strlen(bbuffer)); 
       if (p < 0) 
       error("ERROR writing to socket"); 
       bzero(bbuffer,256); 
       p = read(ssockfd,bbuffer,255); 
       if (p < 0) 
       error("ERROR reading from socket"); 
       printf("%s",bbuffer); // what category? // 
       fgets(bbuffer,255,stdin); 
       p = write(ssockfd,bbuffer,strlen(bbuffer)); 
       if (p < 0) 
       error("ERROR writing to socket"); 
       clientlogs("Client searching for file"); 
       clientlogs(bbuffer); 
       bzero(bbuffer,256); 
       p = read(ssockfd,bbuffer,255); 
       if (p < 0) 
       error("ERROR reading from socket"); 
       printf("%s",bbuffer); //The vector array of the files // 

     } 
     if (bbuffer[0]==wrap[0] && bbuffer[1]==wrap[1]) 
     { p = write(ssockfd,bbuffer,strlen(bbuffer));  
         exit(0);      } 


    }//end of client loop asking to enter a command 

} 




} 


return 0; 

}

+6

請,請嘗試正確縮進和格式化您的代碼。 – jweyrich 2010-10-10 22:02:36

+2

如果你要包含'main()'的大部分代碼,爲什麼不繼續,幷包含一個完整的可編譯的C++程序。 – Potatoswatter 2010-10-10 22:50:00

+0

立即表現出來的是你打開兩個I/O緩衝區到同一個文件。而不是'ifstream'和'ofstream',創建一個'fstream'。如果您必須同時保留兩個文件位置,則至少應使用'file.rdbuf() - > setbuf(0,0);'將兩個對象設置爲不緩衝。 – Potatoswatter 2010-10-10 22:52:26

回答

2

我看到的問題是file << bbuffer。流的<<運算符寫入,直到第一個NULL字節。不要忘記你的緩衝區是一個字符串(或更好的,char *)。因此,如果bbuffer不包含空字節,您的程序很可能會與SIGSEGV一起崩潰。

您應該使用file.write(bbuffer, p)而不是file << bbuffer。此外,無需使用bzeromemset清理緩衝區。

而且因爲你沒有提供編譯源,我寫了下面(假設的Linux/Unix):

#include <cassert> 
#include <iostream> 
#include <fstream> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 

int main() { 
    int fd = socket(AF_INET, SOCK_STREAM, 0); 

    struct sockaddr_in sa_dst; 
    memset(&sa_dst, 0, sizeof(struct sockaddr_in)); 
    sa_dst.sin_family = AF_INET; 
    sa_dst.sin_port = htons(1234); 
    sa_dst.sin_addr.s_addr = inet_addr("127.0.0.1"); 

    int ret = connect(fd, (struct sockaddr *)&sa_dst, sizeof(struct sockaddr)); 
    assert(ret != -1); 

    std::ofstream file; 
    file.open("received.bin", std::ios::out | std::ios::binary); 
    assert(file.is_open()); 
    char buffer[255]; 
    while (1) { 
     std::cout << ".."; 
     ssize_t p = read(fd, buffer, sizeof(buffer)); 
     assert(p != -1); 
     if (p == 0) 
      break; 
     file.write(buffer, p); 
    } 
    file.close(); 
} 

您可以使用終端上的netcat測試:

$ nc -l 1234 < some_binary_file & 
$ ./program 
$ cmp some_binary_file received.bin 
+0

只是爲了完整:請注意,'p == -1'並不一定意味着無法處理的錯誤。當它發生時,你還應該檢查'errno == EAGAIN'(如果它是一個非阻塞的套接字)並且檢查'errno == EINTR'來檢測信號是否中斷了操作。 – jweyrich 2010-10-12 01:52:49

+0

你的代碼似乎不適合我。試圖接收文件時,我的程序仍停滯不前。我知道我可以發送文件,因爲我的搜索功能起作用。我在unix afs機器上。 – thegreattaurus 2010-10-24 22:27:13

+0

@thegreattaurus它停止在哪裏? – jweyrich 2010-10-25 01:28:56