Winpcap : using pcap_stats() for saved files - c++

I have to following problem.
I need to scan a .pcap file (saved file) for re-transmitted tcp packets.
I'm using the Winpcap lib. I tried using pcap_stats() to check for dropped packets (which will also represent re-transmitted packets), but found out pcap_stats() can only be used for live captures and not saved files. Is there any way around this limitation, or am I looking at it wrong?
Here is my code so far:
int main(int argc, char **argv)
{
pcap_t *fp; //File pointer
char errbuff[PCAP_ERRBUF_SIZE]; //Error buffer
char source[PCAP_BUF_SIZE]; //Source string
struct pcap_pkthdr *header; //Packet header
const u_char *pkt_data; //Packet data
pcap_stat *ps; // Packet stats
char packet_filter[] = "tcp"; //Filter paramaters
struct bpf_program fcode; //compiled filter code
int res; //File reading result
u_int i = 0;
time_t start = time(NULL);
time_t sec;
int lps; //Lines per second
//Create source string
if (pcap_createsrcstr(source, //Source string
PCAP_SRC_FILE, //Open local file
NULL, //Host
NULL, //Port
argv[1], //File name
errbuff //Error buffer
) != 0)
{
fprintf(stderr, "\n Error creating source string");
return -1;
}
//Open File
if ((fp = pcap_open(source, //Device
65536, //Capture size (65536 = whole packet)
PCAP_OPENFLAG_PROMISCUOUS, //Flags
1000, //Timeout
NULL, //Authentication
errbuff //Error buffer
)) == NULL)
{
fprintf(stderr, "Error opening file", source);
return -1;
}
//Complie filter
if ((pcap_compile(fp, //File pointer
&fcode, //Compiled filter code
packet_filter, //Filter paramaters
1, //Optimazation
NULL //netmask
)) < 0)
{
fprintf(stderr, "\n Unable to complile packet filter");
return -1;
}
//Set filter
if ((pcap_setfilter(fp, //File pointer
&fcode //Compiled filter code
)) < 0)
{
fprintf(stderr, "\n Error setting filter");
return -1;
}
if ((pcap_stats(fp, ps)) < 0)
{
fprintf(stderr, "failed to retrive statistics");
printf(pcap_geterr(fp));
return -1;
}
//Read file
while ((res = pcap_next_ex(fp, &header, &pkt_data)) >= 0)
{
}
if (res == -1)
{
printf("Error reading the packets %s\n", pcap_geterr(fp));
}
printf("%f%%", (ps->ps_capt)/(ps->ps_recv) * 100); //percentage of accepted packets
sec = time(NULL) - start;
if (sec > 0)
{
lps = (ps->ps_recv) / sec;
printf("\nSpeed: %d Packets/second", lps);
}
else
{
lps = (ps->ps_recv);
printf("\nSpeed: %d Packets/second", lps);
}
return 0;
}

For better or worse, packet statistics are not saved in pcap files; there's nothing in the file format to support that.
pcap-ng supports it, but libpcap doesn't yet support writing pcap-ng files, and WinPcap is based on an earlier version of libpcap that didn't even support reading them.
This will probably improve at some unknown point in the future.

Related

How do I use the FFmpeg libraries to extract every nth frame from a video and save it as a small image file in C++?

After experimenting with the examples on the FFmpeg documentation, I was finally able to create a short program that extracts every nth frame from a video. However, the output files that it produces are huge at over 15mb for each image. How can I change this to produce lower quality images?
The result I am trying to get is done easily on the command line with:
ffmpeg -i [input video] -vf "select=not(mod(n\,10))" -fps_mode vfr img_%03d.jpg
For a video with about 500 frames, this creates 50 images that are only about 800kb each; how am would I be able to mimic this in my program?
My code consists of opening the input file, decoding the packets, then saving the frames:
#include <cstdio>
#include <cstdlib>
#include <iostream>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavutil/opt.h>
#include <libswscale/swscale.h>
}
static AVFormatContext *fmt_ctx;
static AVCodecContext *dec_ctx;
static int video_stream_index = -1;
// OPEN THE INPUT FILE
static int open_input_file(const char *filename) {
// INIT VARS AND FFMPEG OBJECTS
int ret;
const AVCodec *dec;
// OPEN INPUT FILE
if((ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL)) < 0) {
printf("ERROR: failed to open input file\n");
return ret;
}
// FIND STREAM INFO BASED ON INPUT FILE
if((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {
printf("ERROR: failed to find stream information\n");
return ret;
}
// FIND THE BEST VIDEO STREAM FOR THE INPUT FILE
ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0);
if(ret < 0) {
printf("ERROR: failed to find a video stream in the input file\n");
return ret;
}
video_stream_index = ret;
// ALLOCATE THE DECODING CONTEXT FOR THE INPUT FILE
dec_ctx = avcodec_alloc_context3(dec);
if(!dec_ctx) {
printf("ERROR: failed to allocate decoding context\n");
// CAN NOT ALLOCATE MEMORY ERROR
return AVERROR(ENOMEM);
}
avcodec_parameters_to_context(dec_ctx, fmt_ctx->streams[video_stream_index]->codecpar);
// INIT THE VIDEO DECODER
if((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) {
printf("ERROR: failed to open video decoder\n");
return ret;
}
return 0;
}
// SAVE THE FILE
static void save(unsigned char *buf, int wrap, int x_size, int y_size, char *file_name) {
// INIT THE EMPTY FILE
FILE *file;
// OPEN AND WRITE THE IMAGE FILE
file = fopen(file_name, "wb");
fprintf(file, "P6\n%d %d\n%d\n", x_size, y_size, 255);
for(int i = 0; i < y_size; i++) {
fwrite(buf + i * wrap, 1, x_size * 3, file);
}
fclose(file);
}
// DECODE FRAME AND CONVERT IT TO AN RGB IMAGE
static void decode(AVCodecContext *cxt, AVFrame *frame, AVPacket *pkt,
const char *out_file_name, const char *file_ext, int mod=1) {
// INIT A BLANK CHAR TO HOLD THE FILE NAME AND AN EMPTY INT TO HOLD FUNCTION RETURN VALUES
char buf[1024];
int ret;
// SEND PACKET TO DECODER
ret = avcodec_send_packet(cxt, pkt);
if(ret < 0) {
printf("ERROR: error sending packet for decoding\n");
exit(1);
}
// CREATE A SCALAR CONTEXT FOR CONVERSION
SwsContext *sws_ctx = sws_getContext(dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt, dec_ctx->width,
dec_ctx->height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
// CREATE A NEW RGB FRAME FOR CONVERSION
AVFrame* rgb_frame = av_frame_alloc();
rgb_frame->format = AV_PIX_FMT_RGB24;
rgb_frame->width = dec_ctx->width;
rgb_frame->height = dec_ctx->height;
// ALLOCATE A NEW BUFFER FOR THE RGB CONVERSION FRAME
av_frame_get_buffer(rgb_frame, 0);
// WHILE RETURN COMES BACK OKAY (FUNCTION RETURNS >= 0)...
while(ret >= 0) {
// GET FRAME BACK FROM DECODER
ret = avcodec_receive_frame(cxt, frame);
// IF "RESOURCE TEMP NOT AVAILABLE" OR "END OF FILE" ERROR...
if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
return;
} else if(ret < 0) {
printf("ERROR: error during decoding\n");
exit(1);
}
// IF FRAME NUMBER IF THE (MOD)TH FRAME...
if(cxt->frame_number % mod == 0){
// OUTPUT WHICH FRAME IS BEING SAVED
printf("saving frame %03d\n", cxt->frame_number);
// REMOVES TEMPORARY BUFFERED DATA
fflush(stdout);
// SCALE (CONVERT) THE OLD FRAME TO THE NEW RGB FRAME
sws_scale(sws_ctx, frame->data, frame->linesize, 0, frame->height,
rgb_frame->data, rgb_frame->linesize);
// SET "BUF" TO THE OUTPUT FILE PATH (SAVES TO "out_file_name_###.file_ext")
snprintf(buf, sizeof(buf), "%s_%03d.%s", out_file_name, cxt->frame_number, file_ext);
// SAVE THE FRAME
save(rgb_frame->data[0], rgb_frame->linesize[0], rgb_frame->width, rgb_frame->height, buf);
}
}
}
int main() {
// SIMULATE COMMAND LINE ARGUMENTS
char argv0[] = "test";
char argv1[] = "/User/Desktop/frames/test_video.mov";
char *argv[] = {argv0, argv1, nullptr};
// INIT VARS AND FFMPEG OBJECTS
int ret;
AVPacket *packet;
AVFrame *frame;
// ALLOCATE FRAME AND PACKET
frame = av_frame_alloc();
packet = av_packet_alloc();
if (!frame || !packet) {
fprintf(stderr, "Could not allocate frame or packet\n");
exit(1);
}
// IF FILE DOESN'T OPEN, GO TO THE END
if((ret = open_input_file(argv[1])) < 0) {
goto end;
}
// READ ALL THE PACKETS - simple
while(av_read_frame(fmt_ctx, packet) >= 0) {
// IF PACKET INDEX MATCHES VIDEO INDEX...
if (packet->stream_index == video_stream_index) {
// SEND PACKET TO THE DECODER and SAVE
std::string name = "/User/Desktop/frames/img";
std::string ext = "bmp";
decode(dec_ctx, frame, packet, name.c_str(), ext.c_str(), 5);
}
// UNREFERENCE THE PACKET
av_packet_unref(packet);
}
// END MARKER
end:
avcodec_free_context(&dec_ctx);
avformat_close_input(&fmt_ctx);
av_frame_free(&frame);
av_packet_free(&packet);
// FINAL ERROR CATCH
if (ret < 0 && ret != AVERROR_EOF) {
fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
exit(1);
}
exit(0);
}
I am not sure how to go about producing images that are much smaller in size like the ones produced on the command line. I have a feeling that this is possible somehow during the conversion to RGB or the saving of the file but I can't seem to figure out how.
Also, is there any way that I could go about this much more efficiently? On the command line, this finishes very quickly (no more than a second or two for a 9 sec. movie at ~60 fps).
The command line version compresses the frame into jpeg file hence the size is very small. On the other hand, your code writes the rgb values directly into a file (regardless of the file extension). The size of the image is then Height x Width x 3 bytes, which is very big.
Solution: Adjust your save function to also compress the image.
Code example from Github - save_frame_as_jpeg.c:
int save_frame_as_jpeg(AVCodecContext *pCodecCtx, AVFrame *pFrame, int FrameNo)
{
AVCodec *jpegCodec = avcodec_find_encoder(AV_CODEC_ID_JPEG2000);
if (!jpegCodec) { return -1; }
AVCodecContext *jpegContext = avcodec_alloc_context3(jpegCodec);
if (!jpegContext) { return -1; }
jpegContext->pix_fmt = pCodecCtx->pix_fmt;
jpegContext->height = pFrame->height;
jpegContext->width = pFrame->width;
if (avcodec_open2(jpegContext, jpegCodec, NULL) < 0)
{ return -1; }
FILE *JPEGFile;
char JPEGFName[256];
AVPacket packet = {.data = NULL, .size = 0};
av_init_packet(&packet);
int gotFrame;
if (avcodec_encode_video2(jpegContext, &packet, pFrame, &gotFrame) < 0)
{ return -1; }
sprintf(JPEGFName, "dvr-%06d.jpg", FrameNo);
JPEGFile = fopen(JPEGFName, "wb");
fwrite(packet.data, 1, packet.size, JPEGFile);
fclose(JPEGFile);
av_free_packet(&packet);
avcodec_close(jpegContext);
return 0;
}

Correctly reading and writing from socket stream

So, I'm a relative newbie to network programming and programming in general, and I'm attempting to write a simple client/server text file transfer service. My code asks for the user to choose an upload or download option. When the user selects upload, the new file is created on the server's end, but isn't written with the data until the socket is closed. Also the string "upload" is appended onto the end of the text in the file.
I can't seem to find where my errors are, so any help would be greatly appreciated!
server.cpp
#define SIZE 1024
void write_file(int sockfd) // writing data to file function
{
int n;
FILE *fp;
char const *filename = "recv.txt";
char buffer[SIZE];
fp = fopen(filename, "w");
while (1)
{
n = recv(sockfd, buffer, SIZE, 0);
if (n <= 0)
{
break;
}
fprintf(fp, "%s", buffer);
bzero(buffer, SIZE);
}
fclose(fp);
return;
}
// in main
char msgRecv[10];
int n = 10;
while (n > 0)
{
rcv = read(connected_sd, &msgRecv, 10);
n -= rcv;
}
char msgUpload[10] = "upload";
if(strcmp(msgUpload, msgRecv) == 0)
{
write_file(connected_sd);
}
client.cpp
void send_file(FILE *points, int sockfd) // sending file through socket function
{
char bytes[SIZE] = {0};
bzero(bytes, SIZE);
while(fgets(bytes, SIZE, points) != NULL)
{
if(send(sockfd, bytes, sizeof(bytes), 0) == -1)
{
perror("Error in sending file.");
exit(1);
}
bzero(bytes, SIZE);
}
}
// in main
char msgUpload[10] = "upload";
send(sd, msgUpload, sizeof(msgUpload), 0);
string fileN;
cout << "What is the name of the file you wish to upload?\n";
cin >> fileN;
bzero(msgUpload, sizeof(msgUpload));
FILE *file;
char const *filename = fileN.c_str();
file = fopen(filename, "r");
if (file == NULL)
{
perror("Error in reading file.\n");
exit(1);
}
send_file(file, sd);
printf("File data sent successfully.\n\n");
fclose(file);

How do I send and receive packets in RTP session (using jrtplib) with variable lenght?

Lately I have installed jrtplib (C++) and I'm trying to understand how I should receive data from packets, save them to one buffer and at the end of the transmission save that whole data to a file. So far I have got this (mostly from example files provided with library).
This is the server:
using namespace jrtplib;
int main(void)
{
#ifdef RTP_SOCKETTYPE_WINSOCK
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
#endif // RTP_SOCKETTYPE_WINSOCK
RTPSession sess;
uint16_t portbase = 5000;
RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;
// IMPORTANT: The local timestamp unit MUST be set, otherwise
// RTCP Sender Report info will be calculated wrong
// In this case, we'll be sending 10 samples each second, so we'll
// put the timestamp unit to (1.0/10.0)
sessparams.SetOwnTimestampUnit(1.0/10.0);
sessparams.SetAcceptOwnPackets(true);
transparams.SetPortbase(portbase);
int status;
status = sess.Create(sessparams,&transparams);
checkerror(status);
bool done = false;
std::cout << "Waiting for some data...\n";
RTPTime startTime = RTPTime::CurrentTime();
std::vector<int8_t> data;
while(!done)
{
std::cout << "Waiting for some data...\n";
sess.BeginDataAccess();
// check incoming packets
if (sess.GotoFirstSourceWithData())
{
do
{
RTPPacket *pack;
while ((pack = sess.GetNextPacket()) != NULL)
{
// You can examine the data here
data.push_back(*(pack->GetPayloadData()));
// we don't longer need the packet, so
// we'll delete it
sess.DeletePacket(pack);
}
} while (sess.GotoNextSourceWithData());
}
sess.EndDataAccess();
#ifndef RTP_SUPPORT_THREAD
status = sess.Poll();
checkerror(status);
#endif // RTP_SUPPORT_THREAD
RTPTime::Wait(RTPTime(0.020));
RTPTime t = RTPTime::CurrentTime();
t -= startTime;
if ( t > RTPTime(100.0) ) {
done = true;
}
}
sess.BYEDestroy(RTPTime(10,0),0,0);
#ifdef RTP_SOCKETTYPE_WINSOCK
WSACleanup();
#endif // RTP_SOCKETTYPE_WINSOCK
FILE *file = fopen("d:/file.png", "w");
if (file == NULL){
printf("Could not open file for saving!\n");
exit(1);
}
for (int i = 0; i < data.size(); i++){
fwrite(&data[i], sizeof(data[i]), 1, file);
}
return 0;
}
And this is the client:
using namespace jrtplib;
int main()
{
#ifdef RTP_SOCKETTYPE_WINSOCK
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
#endif
FILE *file = fopen("c:/file.png", "rb");
if (file == NULL){
printf("Could not open file!\n");
exit(1);
}
fseek(file, 0L, SEEK_END);
auto fsize = ftell(file);
fseek(file, 0L, SEEK_SET);
printf("File size: %ld\n", fsize);
auto *buffer = (unsigned char*) malloc(fsize);
fread(buffer, fsize, 1, file);
fclose(file);
file = NULL;
uint16_t portbase = 5000;
uint16_t destport = 5000;
std::string ipstr = "192.168.1.164";
uint32_t destip = inet_addr(ipstr.c_str());
if (destip == INADDR_NONE)
{
std::cerr << "Bad IP address specified" << std::endl;
return -1;
}
destip = ntohl(destip);
/* Parameters for the transmission component */
RTPUDPv4TransmissionParams transparams;
transparams.SetPortbase(portbase);
RTPSessionParams sessparams;
sessparams.SetOwnTimestampUnit(1.0/10.0);
sessparams.SetAcceptOwnPackets(true);
// Give general options for session
RTPSession sess;
int status = sess.Create(sessparams,&transparams);
checkerror(status);
sess.SetDefaultPayloadType(96);
sess.SetDefaultMark(false);
sess.SetDefaultTimestampIncrement(160);
/* Specify to which destinations rtp and rtcp data should be sent. */
RTPIPv4Address addr(destip,destport);
status = sess.AddDestination(addr);
checkerror(status);
RTPTime delay(0.020);
RTPTime starttime = RTPTime::CurrentTime();
int transmitted = 0;
auto *p = buffer;
bool done = false;
while(!done) {
// send the packet
status = sess.SendPacket(p, sizeof(*p));
checkerror(status);
transmitted += sizeof(*p);
p++;
RTPTime::Wait(delay);
RTPTime t = RTPTime::CurrentTime();
t -= starttime;
if (t > RTPTime(100.0)){
*buffer = 0;
status = sess.SendPacket(p, sizeof(*p));
transmitted += sizeof(*p);
done = true;
}
printf("\nSent %d bytes\n", transmitted);
}
sess.BYEDestroy(RTPTime(10,0),0,0);
#ifdef RTP_SOCKETTYPE_WINSOCK
WSACleanup();
#endif
return 0;
}
I have succeded in sending small text files, but only if I knew the exact size of the file - I modified the server to stop at the exact ammount of received bytes to do that. The second thing is that I always receive 1 byte at once to the 1 byte vector: vector of int8_t. For now i just know I am sending 1 byte at a time.
The questions are:
How do I stop the transmission when I know it is finished (from client and server side)?
How do I send data that varies in length and how do I receive it if I don't know how much will be sent? That way I don't think I can save all the data to the vector, so how should I store it in memory if the buffer size constantly increases?
I know that RTP is used for real-time transmissions (which I intend to use it for later) but for now I just wanted to grasp the basic concepts of networking.

Saving frames as images using FFmpeg

There are some tutorials on the internet about it, most of them is using deprecated functions and unfortunately the API use to broke and it makes a mess and I'm really confused.
I'm following tutorials, learning with the documentation and seeing the examples of the current version (even that way some examples does not work).
What I'm trying to do is to save frames in .png, following the examples and reading I did this, but I'm confused about the conversion the frame to RBG and saving it:
#include <iostream>
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
}
int main(int argc, char ** argv)
{
if (argc < 2)
{
av_log(0, AV_LOG_FATAL, "Usage: %s <input>", argv[0]);
return -1;
}
const char * filename = argv[1];
// register all codecs and formats
av_register_all();
// open input file, and allocate format context
AVFormatContext *avFormatContext = avformat_alloc_context();
if (avformat_open_input(&avFormatContext, filename, 0, 0) < 0)
{
av_log(0, AV_LOG_FATAL, "Could not open source file %s", filename);
return -1;
}
// retrieve stream information
if (avformat_find_stream_info(avFormatContext, 0) < 0)
{
av_log(0, AV_LOG_FATAL, "Could not find stream information");
return -1;
}
// dump information about file onto standard error
av_dump_format(avFormatContext, 0, filename, 0);
// find the "best" video stream in the file.
int result = av_find_best_stream(avFormatContext, AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0);
if (result < 0)
{
av_log(0, AV_LOG_FATAL, "Could not find %s stream in input file '%s'", av_get_media_type_string(AVMEDIA_TYPE_VIDEO), filename);
return -1;
}
int stream = result;
AVStream *avStream = avFormatContext->streams[stream];
AVCodecContext *avCodecContext = avStream->codec;
// find decoder for the stream
AVCodec *avCodec = avcodec_find_decoder(avCodecContext->codec_id);
if (! avCodec)
{
av_log(0, AV_LOG_FATAL, "Failed to find %s codec", av_get_media_type_string(AVMEDIA_TYPE_VIDEO));
return -1;
}
// init the decoders, with reference counting
AVDictionary *avDictionary = 0;
av_dict_set(&avDictionary, "refcounted_frames", "1", 0);
if (result = avcodec_open2(avCodecContext, avCodec, &avDictionary) < 0)
{
av_log(0, AV_LOG_FATAL, "Failed to open %s codec", av_get_media_type_string(AVMEDIA_TYPE_VIDEO));
return -1;
}
AVFrame *avFrame = av_frame_alloc();
if (! avFrame)
{
av_log(0, AV_LOG_FATAL, "Could not allocate frame");
return -1;
}
// initialize packet, set data to null, let the demuxer fill it
AVPacket avPacket;
av_init_packet(&avPacket);
avPacket.data = 0;
avPacket.size = 0;
while (av_read_frame(avFormatContext, &avPacket) >= 0)
{
if (avPacket.stream_index == stream)
{
int success = avcodec_decode_video2(avCodecContext, avFrame, &success, &avPacket);
if (success <= 0)
{
av_log(0, AV_LOG_FATAL, "Error decoding video frame");
return -1;
}
// ... saving...
}
}
avcodec_close(avCodecContext);
avformat_close_input(&avFormatContext);
av_frame_free(&avFrame);
return 0;
}

Failed to send file via socket

I'm working with some C++ socket examples. The client run and can connect to the server but can't send the file. I think there's a problem with the send() but I can't fix it.Edit: the error message is "connection reset by peer"
Any ideas are welcomed.
I use OpenSuSE with QT 4.7.4
Here's the send and receive function
void str_server(int sock)
{
char buf[1025];
const char* filename = "//home//romanov//Documents//HelloWorld-build-desktop-Qt_4_7_4_in_PATH__System__Release//ss.png";
FILE *file = fopen(filename, "rb");
if (!file)
{
cerr<<"Can't open file for reading";
return;
}
while (!feof(file))
{
int rval = fread(buf, 1, sizeof(buf), file);//read value
if (rval < 1)
{
cerr<<"Can't read from file";
fclose(file);
return;
}
int off = 0;
do
{
int sent = send(sock, &buf[off], rval - off, 0);
if (sent < 1)
{
// if the socket is non-blocking, then check
// the socket error for WSAEWOULDBLOCK/EAGAIN
// (depending on platform) and if true then
// use select() to wait for a small period of
// time to see if the socket becomes writable
// again before failing the transfer...
cout<<"Can't write to socket";
fclose(file);
return;
}
off += sent;
}
while (off < rval);
}
fclose(file);
}
//===================
void RecvFile(int winsock)
{
int rval;
char buf[1025];
FILE *file = fopen("//home//romanov//Documents//HelloWorld-build-desktop-Qt_4_7_4_in_PATH__System__Release//ss2.png", "wb");
if (!file)
{
printf("Can't open file for writing");
return;
}
do
{
rval = recv(winsock, buf, sizeof(buf), 0);
if (rval < 0)
{
// if the socket is non-blocking, then check
// the socket error for WSAEWOULDBLOCK/EAGAIN
// (depending on platform) and if true then
// use select() to wait for a small period of
// time to see if the socket becomes readable
// again before failing the transfer...
printf("Can't read from socket");
fclose(file);
return;
}
if (rval == 0)
break; //line 159
int off = 0;
do
{
int written = fwrite(&buf[off], 1, rval - off, file);
if (written < 1)
{
printf("Can't write to file");
fclose(file);
return;
}
off += written;
}
while (off < rval);
} //line 175
while (1);
fclose(file);
}
Well , the problem is my bad, I read the wrong socket in the recvFile() , if you guys encounter the same problem, you should check it out.