Từ 1 tới 3 trên tổng số 3 kết quả

Đề tài: Lỗi ghi file bởi hàm fwrite từ luồng phụ

  1. #1
    Ngày gia nhập
    04 2009
    Bài viết
    57

    Angry Lỗi ghi file bởi hàm fwrite từ luồng phụ

    Mình đang nghiên cứu về Winsock và viết 1 chương trình tải file đơn giản sau gồm 2 phần
    FileClient: gửi yêu cầu đến máy server
    FileServer: thực hiện các xử lý từ FileClient

    FileClient: sẽ gửi dạng sau: GET <Ten file>
    FileServer sẽ tách tên file và truy xuất vào file đó.

    Dưới đây là code của 2 phần:
    FileClient:
    C++ Code:
    1. // FileClient.cpp : Defines the entry point for the console application.
    2. //
    3.  
    4. #include "stdafx.h"
    5. #include <winsock2.h>
    6. #include <stdio.h>
    7. #include <conio.h>
    8. #include <stdlib.h>
    9. #pragma comment (lib,"ws2_32.lib");
    10.  
    11. FILE *fp;
    12. SOCKET client;
    13. char filename[10];
    14. int q = 0;
    15. int i = 0;
    16. int k = 0;
    17.  
    18. DWORD WINAPI ReceiverThread(LPVOID lpParameter)
    19. {
    20.     char buf[1024];
    21.     if(fopen_s(&fp,"Test1.txt","w+") != 0)
    22.         printf("File is not found.\n");
    23.     //fp = stdout;
    24.     while(1){         //Bắt đầu ghi ra file
    25.        int ret = recv(client,buf,strlen(buf),0);
    26.        if(ret > 0)
    27.        {
    28.                buf[ret] = 0;
    29.                q = strlen(buf);
    30.                fwrite(buf,sizeof(char),q,fp);
    31.             }
    32.         else
    33.            printf("Ham recv() bi loi %d",WSAGetLastError());
    34.     }
    35.     fclose(fp);
    36.     return 0;
    37. }
    38.  
    39.  
    40. int _tmain(int argc, _TCHAR* argv[])
    41. {
    42.     SOCKADDR_IN clientAddr;
    43.     int size = sizeof(clientAddr);
    44.     int ret;
    45.     WSAData wsaData;
    46.     WSAStartup(MAKEWORD(2,2),&wsaData);
    47.     client = socket(AF_INET,SOCK_STREAM,0);
    48.     if(client == INVALID_SOCKET)
    49.         printf("\nSocket ko hop le va loi: %d\n",WSAGetLastError());
    50.  
    51.     clientAddr.sin_family = AF_INET;
    52.     clientAddr.sin_port = htons(8888);
    53.     clientAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    54.         char buf[1024],buf_rec[100];
    55.    
    56.     ret = connect(client,(sockaddr*)&clientAddr,size);
    57.     if(ret != 0)
    58.         printf("\nHam connect() bi loi %d",WSAGetLastError());
    59.     else
    60.         printf("Da ket noi thanh cong    [%s]:[%d]\n",inet_ntoa(clientAddr.sin_addr),ntohs(clientAddr.sin_port));
    61.    
    62.         memset(buf,0,strlen(buf));
    63.     memset(buf_rec,0,strlen(buf_rec));
    64.     //while(1)
    65.     //{
    66.                //Gửi yêu cầu tải file Test1.txt
    67.         strcat(buf,"GET ");
    68.                 strcat(buf, "Test1.txt\n");
    69.  
    70.           ret = send(client,buf,strlen(buf),0);
    71.         //ret = (int)CreateThread(0,0,ReceiverThread,0,0,0);
    72.               if(ret > 0)
    73.                 ret = (int)CreateThread(0,0,ReceiverThread,0,0,0);
    74.          while(1)
    75.          {
    76.  
    77.          }
    78.  
    79.        
    80.     //}
    81.  
    82.     closesocket(client);
    83.     WSACleanup();
    84.     _getch();
    85.     return 0;
    86. }


    FileServer:
    C++ Code:
    1. // FileServer.cpp : Defines the entry point for the console application.
    2. //
    3.  
    4. #include "stdafx.h"
    5. #include <winsock2.h>
    6. #include <stdio.h>
    7. #include <conio.h>
    8. #include <string.h>
    9. #include <stdlib.h>
    10. #pragma comment (lib,"ws2_32.lib")
    11.  
    12. SOCKET server,newconnection;
    13. FILE *fp,*fcapa;
    14. char filename[1024];
    15. int sizefile,count,ret;
    16. bool isFirst = TRUE;
    17. char tmp[6];
    18.  
    19. DWORD WINAPI SendThread(LPVOID lpParameter)
    20. {
    21.     char buf[100] = "OK ";
    22.     char temp[100];
    23.     if((fopen_s(&fp,filename,"r"))!= 0)
    24.         printf("File %s is not found.",filename);
    25.     fopen_s(&fcapa,filename,"r");
    26.     fseek(fcapa,0L,SEEK_END);
    27.     sizefile = ftell(fcapa) - 1; //Lay kich thuoc file
    28.     strcat(buf,filename);
    29.     strcat(buf,"\n");
    30.     strcat(buf,"Size:");
    31.     strcat(buf,_itoa(sizefile,tmp,10));
    32.     strcat(buf,"\n\n");
    33.     while(!feof(fp))
    34.     {
    35.        count = fread(temp,sizeof(char),4,fp);//doc tu con trỏ file ra buffer
    36.        if(count != 0)
    37.        {
    38.            temp[count] = 0;
    39.            if(isFirst)
    40.            {
    41.               strcat(buf,temp);
    42.               ret = send(newconnection,buf,strlen(buf),0);
    43.            }
    44.            else
    45.                ret = send(newconnection,temp,strlen(temp),0);
    46.  
    47.            if(ret == 0)
    48.                printf("Ham send() trong luong phu bi loi %d",WSAGetLastError());
    49.  
    50.            isFirst = FALSE;
    51.        }
    52.     }
    53.  
    54.            fclose(fp);
    55.        fclose(fcapa);
    56.        return 0;
    57. }
    58.  
    59. int _tmain(int argc, _TCHAR* argv[]){
    60.     SOCKADDR_IN serverAddr,clientAddr;
    61.     int size = sizeof(clientAddr);
    62.     WSAData wsaData;
    63.     char buf[1024];
    64.     int ret,i;
    65.     argv[1] = "8888";
    66.     WSAStartup(MAKEWORD(2,2),&wsaData);
    67.     server = socket(AF_INET,SOCK_STREAM,0);
    68.     if(server == INVALID_SOCKET)
    69.         printf("Ham socket() loi %d",WSAGetLastError());
    70.  
    71.     serverAddr.sin_family = AF_INET;
    72.     serverAddr.sin_port = htons(8888);
    73.     serverAddr.sin_addr.s_addr = htonl(0);
    74.  
    75.         ret = bind(server,(sockaddr*)&serverAddr,sizeof(serverAddr));
    76.     if(ret != 0)
    77.         printf("Ham bind() loi %d\n",WSAGetLastError());
    78.  
    79.     ret = listen(server,10);
    80.     if(ret != 0)
    81.         printf("Ham listen() loi %d\n",WSAGetLastError());
    82.  
    83.     newconnection = accept(server,(sockaddr*)&clientAddr,&size);
    84.     if(newconnection == INVALID_SOCKET)
    85.         printf("Ham accept() loi %d\n",WSAGetLastError());
    86.  
    87.     while(1)
    88.     {
    89.         ret = recv(newconnection,buf,strlen(buf),0);
    90.         if(ret > 0)
    91.         {
    92.             buf[ret] = 0;
    93.             int len = strlen(buf);
    94.             if(strncmp(buf,"GET",3) == 0)
    95.             {
    96.               //Lay ten file
    97.               for(i = 0; i < len - 5; i++)
    98.                    filename[i] = buf[i + 4];
    99.               filename[i] = 0;
    100.               //Goi luong gui
    101.               ret = (int)CreateThread(0,0,SendThread,0,0,0);
    102.             }
    103.             else
    104.             {
    105.                 memset(buf,0,sizeof(buf));
    106.                 strcpy(buf,"Unknown Command");
    107.                 ret = send(newconnection,buf,strlen(buf),0);
    108.                 if(ret == 0)
    109.                     printf("Ham send() bi loi: %d",WSAGetLastError());
    110.             }
    111.         }
    112.     }
    113.  
    114.     closesocket(newconnection);
    115.     closesocket(server);
    116.     WSACleanup();
    117.     _getch();
    118.     return 0;
    119. }


    Vấn đề phát sinh ở luồng nhận ReceiverThread bên Client.
    Trường hợp 1: mình cho fp trỏ vào file
    Nếu mình debug từng dòng trong luồng thì toàn bộ nội dung của buf sẽ được ghi vào file.
    Nhưng nếu mình chạy ở chế độ Running thì chỉ có OK <tenfile>\n Size: <kich thuoc file> được ghi ra file.
    Trường hợp 2:( ở dòng 23) mình cho fp trỏ vào dòng stdout(mục đích là để test dữ liệu nhận đến thôi vì trường hợp 1 mình ko ghi hết được ra file)
    thì ghi ra được hết lên console.

    Mình ko rõ lỗi phát sinh do đâu. Debug thì chạy đúng nhưng khi Running thì ko ghi được hết.

    Link tới project của mình: Chương trình tải file
    Đã được chỉnh sửa lần cuối bởi svcntt : 31-07-2011 lúc 08:47 PM.

  2. #2
    Ngày gia nhập
    11 2007
    Nơi ở
    Hà Nội
    Bài viết
    520

    Rất có thể lỗi bên phía server bạn ạ, nó không mở được file nên không gửi được, mà đã không gửi được thì chả có gì để nhận cả

    Mà mình thấy bạn thiết kế cái message gửi file như thế là không hợp lý
    1 bên cắm cúi gửi, một bên cứ nhắm mắt nhận

    Giao thức nên theo kiểu sau: Có tên file, offset của vị trí muốn nhận dữ liệu trong file, size của dữ liệu cần nhận

    như thế khi Client request 1 đoạn dữ liệu thì bên server gửi đúng yêu cầu thế thôi, nếu chết giữa chừng còn có thể resume được, và chỉ tải phần đã thiếu

    Code:
     int ret = recv(client,buf,strlen(buf),0);
           if(ret > 0)
           {
                   buf[ret] = 0;
                   q = strlen(buf);
                   fwrite(buf,sizeof(char),q,fp);
                }
            else
               printf("Ham recv() bi loi %d",WSAGetLastError());
    ghi file thế này, chỉ dùng được nếu là file văn bản thôi , trường hợp file nhị phân thì chắc chắn lỗi nặng, khi truyền file nhị phân, nhất định trong đoạn dữ liệu sẽ có byte 0, như thế size bên gửi và bên nhận sẽ khác nhau, để giải quyết vấn đề này, bạn có thể encode trước khi gửi thành dạng Base64 trước khi gửi.

    trông cái cổng 8888, buffer size là 1024, mình đoán bạn đang học lập trình mạng, kì hè, bkhn ???

  3. #3
    Ngày gia nhập
    04 2009
    Bài viết
    57

    Mặc định Lỗi ghi file bởi hàm fwrite từ luồng phụ

    Mình sẽ chú ý tới 2 vấn đề sau:
    +, Thiết kế lại message yêu cầu gửi file
    +, Gửi file nhị phân trong trường hợp client y/cầu file nhị phân.

    Nhưng trước hết , phải làm để chạy được chương trình trên với file văn bản đã. Sau đó, mới mở rộng cho 2 vấn đề như bạn nêu trên.
    Cái chương trình FileServer ko chạy sai đâu. Mình chạy FileServer, rồi debug FileClient( ở chỗ luồng ReceiverThread ấy), sau khi debug qua hàm recv, thì buf chứa đầy đủ nội dung của file mà.( Như vậy bên server đã mở được file Test1.txt và lấy dữ liệu gửi về được rồi, thì hàm recv của client mới lấy được dữ liệu cho vào buf chứ). Cái mình quan tâm là ở hàm fwrite, mình debug qua nó, toàn bộ dữ liệu của buf được ghi ra file. Sau đó, xóa cái file Test1.txt trong thư mục project FileClient, chạy FileClient thì Test1.txt được tạo lại và nội dung chỉ có dòng OK <tenfile> Size:<kt file> còn lại nội dung file được yêu cầu thì ko thấy.

    P/S: Mình ngồi nghe nhờ lớp Lập trình mạng thôi, thấy thiết thực nên mình muốn tìm hiểu luôn. Vì đằng nào, năm sau cũng phải học môn này mà.

Các đề tài tương tự

  1. Cấu trúc lệnh fwrite() trong c++
    Gửi bởi minhson.uit trong diễn đàn Nhập môn lập trình C/C++
    Trả lời: 3
    Bài viết cuối: 22-08-2012, 01:57 PM
  2. Lập trình C Lỗi đọc file và ghi file với fread, fwrite :(
    Gửi bởi philip12a8 trong diễn đàn Nhập môn lập trình C/C++
    Trả lời: 3
    Bài viết cuối: 22-12-2011, 10:10 AM
  3. Bài tập C sủ dụng hàm fread và fwrite bị lỗi
    Gửi bởi laimotlanuabi trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 2
    Bài viết cuối: 01-05-2011, 12:47 AM
  4. Bài tập C Cách dùng hàm fwrite để ghi kiểu dữ liệu cấu trúc ra tệp nhị phân
    Gửi bởi Thien Phuc trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 6
    Bài viết cuối: 01-04-2011, 09:41 AM
  5. lỗi đọc ghi file dùng hàm fwrite và fread
    Gửi bởi supnobita trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 0
    Bài viết cuối: 02-01-2011, 08:42 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn