send multiple pics from folder via socket

Pages: 12
I would like to start a fresh thread in order to solve this issue
that has been going for awhile.

I am trying to send all the pictures from a folder via socket.
The code runs but line 125 prints 0 bytes and no transfer occurs.

I am not sure what is happening.
I would like to know how to fix my code in order to be able to send these pictures.

(I will post my python client too)

SERVER
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <unistd.h> 
#include <stdio.h> 
#include <sys/socket.h> 
#include <stdlib.h> 
#include <netinet/in.h> 
#include <string.h> 
#define PORT 8080 
#include <string.h>
#include <arpa/inet.h>   
#include <iostream>
#include <fstream>
#include <errno.h>
#include<vector>

#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>

using namespace std;


int main(int argc, char const *argv[]) 
{ 
    int s, new_socket, valread; 
    struct sockaddr_in address; 
   
   if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
    { 
        perror("socket failed"); 
        exit(1); 
    } 
     address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);
       
    //  attach socket to port 
if (bind(s,(struct sockaddr *)&address , sizeof(address)) < 0)
    { 
        perror("bind failed"); 
        exit(1); 
    } 
    listen(s, 3);
    
    
if(new_socket= accept(s, (struct sockaddr *) 0, 0))
{puts("Connection accepted");}
        
        char buff[24] ;
        char *msg=(char*)"hi from server";
      
        int received_bytes = 0;
        int remaining_bytes = sizeof(buff);
        send(new_socket , msg , strlen(msg) , 0 ); 
        printf("Message sent ");    

            
while((remaining_bytes > 0) ){
        
   
    if (new_socket == -1)                  
    { 
        perror("accept"); 
        exit(1); 
    } 
    else
        {
        
        int res = recv(new_socket , &buff[received_bytes],remaining_bytes,0);
        received_bytes += res;
        remaining_bytes -= res;
     }

}printf("%s\n\n",buff);

//send image sizes to client//
const char *dir = "/home/Desktop/pics";

    if (chdir(dir) == -1) {
        perror(dir);
        return 1;
    }

    DIR *dirp = opendir(".");

    for (struct dirent *dent; (dent = readdir(dirp)) != NULL; )
    {
        const char *nm = dent->d_name;

        if (strcmp(nm, ".") == 0 || strcmp(nm, "..") == 0)
            continue;

        struct stat file_stats;
        if (stat(nm, &file_stats) == -1)
            perror(nm);

        else
            printf("%9u: %s\n", (unsigned)file_stats.st_size, nm);
char folder[(unsigned)file_stats.st_size];

sprintf(folder, "home/Desktop/pics/%s", nm );
cout<<"here is the folder ------"<<folder<<endl;



long converted_number = htonl((unsigned)file_stats.st_size);
char buff_1[8] ;
int buff_1_size=sizeof(buff_1);
int i;
//for (i=0; i<=buff_1_size; i++)
//{
//if ((converted_number > 0))
//{
//int sb=send(new_socket, &converted_number, sizeof(converted_number), 0);
send(new_socket, &converted_number, sizeof(converted_number), 0);
//cout<<"bytes sent are ===="<<sb<<endl;
//}
//}




ifstream stream(folder, std::ios::in | std::ios::binary);
vector<char> imageDataVec((istreambuf_iterator<char>(stream)), istreambuf_iterator<char>());
cout << "Size: " << imageDataVec.size() << " bytes";
long conv_num= htonl(imageDataVec.size());
//send(new_socket, &converted_number, sizeof(converted_number), 0);
//send(new_socket, &imageDataVec, imageDataVec.size() , 0);

size_t sent{};
while (sent < imageDataVec.size()) {
 //   send(new_socket, &converted_number, sizeof(conv_num), 0);
    int nbytes = send(new_socket, &imageDataVec[sent], imageDataVec.size() - sent, 0);
    if (nbytes <= 0) {
        std::clog << "error: while sending image\n";
        break;
    
    sent += nbytes;
    cout<<nbytes<<"================"<<endl;
}
 


closedir(dirp);
}
}
// send_image(new_socket);
    close(s);
    close(new_socket);
    return 0; 
} 


CLIENT (python)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/usr/bin/env python3

import socket
import numpy as np
import cv2
from PIL import Image
from io import BytesIO, StringIO
import os
import time
import sys
import ssl

import pickle
import struct

host = '127.0.0.1'
port = 8080
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
print("connected to the server")

msg_to_server=("hi from client ".encode())
msg_to_server_2=("hi again ".encode())
bytes_in_message=sys.getsizeof(msg_to_server)


from_server = s.recv(1024)
print("received message",from_server)
print(type(from_server))


s.send(msg_to_server)
s.send(msg_to_server_2)

print(bytes_in_message) 
number_of_pics=5
list_of_bytes=[]
for i in range(5*2):
    data = s.recv(4)
    if b'\x00\x00\x00\x00' in data:
        continue
  
    print(data)
    data_bytes_amount = int.from_bytes(data, byteorder='big', signed=False)
    
    print("received size={}".format(data_bytes_amount))
    total_received = len(data)
    print("total received ==== ", total_received)
    
    if data_bytes_amount!=0:
        list_of_bytes.append(data_bytes_amount)
    
print(list_of_bytes)
print("sum of bytes======", sum(list_of_bytes))
print(type(len(list_of_bytes)))



pic_bytes=s.recv(sum(list_of_bytes))
pic_bytes_amount=int.from_bytes(pic_bytes, byteorder='big', signed=False)
#print("received bytes======{}".format(pic_bytes_amount))
f=open('pic.jpeg','wb')
f.write(pic_bytes)
f.close()
Last edited on
Cleaned up dog food.
And a bunch of crappy mistakes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#define PORT 8080
#include <string.h>
#include <arpa/inet.h>
#include <iostream>
#include <fstream>
#include <errno.h>
#include<vector>

#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>

using namespace std;

int main(int argc, char const *argv[])
{
  int s, new_socket, valread;
  struct sockaddr_in address;

  if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    perror("socket failed");
    exit(1);
  }
  address.sin_family = AF_INET;
  address.sin_addr.s_addr = INADDR_ANY;
  address.sin_port = htons(PORT);

  //  attach socket to port 
  if (bind(s, (struct sockaddr *) &address, sizeof(address)) < 0) {
    perror("bind failed");
    exit(1);
  }
  listen(s, 3);

  if (new_socket = accept(s, (struct sockaddr *) 0, 0)) {
    puts("Connection accepted");
  }

  char buff[24];
  char *msg = (char *) "hi from server";

  int received_bytes = 0;
  int remaining_bytes = sizeof(buff);
  send(new_socket, msg, strlen(msg), 0);
  printf("Message sent ");

  while ((remaining_bytes > 0)) {
    if (new_socket == -1) {
      perror("accept");
      exit(1);
    } else {
      int res = recv(new_socket, &buff[received_bytes], remaining_bytes, 0);
      received_bytes += res;
      remaining_bytes -= res;
    }
  } 
  printf("%s\n\n", buff);

//send image sizes to client//
  const char *dir = "/home/Desktop/pics";
  if (chdir(dir) == -1) {
    perror(dir);
    return 1;
  }

  DIR *dirp = opendir(".");

  for (struct dirent * dent; (dent = readdir(dirp)) != NULL;) {
    const char *nm = dent->d_name;

    if (strcmp(nm, ".") == 0 || strcmp(nm, "..") == 0)
      continue;

    struct stat file_stats;
    if (stat(nm, &file_stats) == -1)
      perror(nm);
    else
      printf("%9u: %s\n", (unsigned) file_stats.st_size, nm);

    char folder[(unsigned) file_stats.st_size];

    sprintf(folder, "home/Desktop/pics/%s", nm);
    cout << "here is the folder ------" << folder << endl;

    long converted_number = htonl((unsigned) file_stats.st_size);
    char buff_1[8];
    int buff_1_size = sizeof(buff_1);
    int i;
//for (i=0; i<=buff_1_size; i++)
//{
//if ((converted_number > 0))
//{
//int sb=send(new_socket, &converted_number, sizeof(converted_number), 0);
    send(new_socket, &converted_number, sizeof(converted_number), 0);
//cout<<"bytes sent are ===="<<sb<<endl;
//}
//}

    ifstream stream(folder, std::ios::in | std::ios::binary);
    vector < char >imageDataVec((istreambuf_iterator < char >(stream)), istreambuf_iterator < char >());
    cout << "Size: " << imageDataVec.size() << " bytes";
    long conv_num = htonl(imageDataVec.size());
//send(new_socket, &converted_number, sizeof(converted_number), 0);
//send(new_socket, &imageDataVec, imageDataVec.size() , 0);

    size_t sent {
    };
    while (sent < imageDataVec.size()) {
      //   send(new_socket, &converted_number, sizeof(conv_num), 0);
      int nbytes = send(new_socket, &imageDataVec[sent], imageDataVec.size() - sent, 0);
      if (nbytes <= 0) {
        std::clog << "error: while sending image\n";
        break;

        sent += nbytes;
        cout << nbytes << "================" << endl;
      }
      closedir(dirp);
    }
  }
// send_image(new_socket);
  close(s);
  close(new_socket);
  return 0;
}

1.
1
2
    char folder[(unsigned) file_stats.st_size];
    sprintf(folder, "home/Desktop/pics/%s", nm);

Explain what you think is happening here.
The size of a file has absolutely NO relevance to the length of the filename.

2. Look where your closedir() is. Assuming success, you're only sending one image before it blows up in your face.

3. A bloated and poorly indented main is ripe for lots of unforced errors because you can't keep everything organised. I gave you some structure in a previous post, but you're just ignoring anyone who attempts to steer you away from bloat city.

4. Try adding more error checks.
The reason your printed size is zero is probably because the previous line didn't open the file at all.
I asked for help, and not to be insulted.

"char folder[]": I wrote this because I need a buff size.
sprintf: I am looking to send the files as a char array, since it worked for sending one image.

A bloated and poorly indented main is ripe for lots of unforced errors because you can't keep everything organised. I gave you some structure in a previous post, but you're just ignoring anyone who attempts to steer you away from bloat city.


this is the way I do my work, and as a programmer, I'm sure you know that we all have our ways of writing.
I diverged from your post because
a- I would rather stick to something that I write, therefore , understand, and eventually change a bit in order to make it work,
b- your past code as more than a few mistakes, so is not possible for me to run it.


So in the end, I am trying to fix my code and make it work, but all I got from you was insults and nonsense sarcasm, meanwhile you didn't bother to change a single line. If you wanna be in this forum I would suggest you to be more helpful by giving constructive criticism and specifically addressing the mistakes that we bring, or else there is no point for you to participate to our threads.
can anyone tell me how to fix my code to make it work?
Before you continue, you should make sure the the hello messages work. Is it so?

The port 8080 is certainly not a good choice. It often used for web services.

Line 99 doesn't make sense. You have a variable length array for the file name that takes the size of the entire file. Better use std::string instead.

Line 123: Make sure that the file could be open before you use it.
Maybe just put the files on a CD and send them by snail mail.
Before you continue, you should make sure the the hello messages work. Is it so?


Yes, it works perfectly fine

The port 8080 is certainly not a good choice. It often used for web services.

when I send hello messages and only 'one' picture, everything works fine, so it doesn't seem to be the issue.

Line 99 doesn't make sense. You have a variable length array for the file name that takes the size of the entire file. Better use std::string instead.

I changed the parameter recently just to experiment, the number between [ ] used to be 100, but I got the same problems.

Line 123: Make sure that the file could be open before you use it.

I tried with FILE *fin = fopen(nm, "rb");
but i am not sure how to implement this to the rest of the code.
Would you kindly show me how?
but i am not sure how to implement this to the rest of the code.
I mean something like this:
1
2
3
4
5
6
7
    ifstream stream(folder, std::ios::in | std::ios::binary);
    if(stream.is_open())
    {
....
    }
    else
        cout << folder << " cannot be opened" << endl
See:

http://www.cplusplus.com/reference/fstream/fstream/is_open/

[EDIT] You set it within the comparison...
Take a look at this:
1
2
  for (struct dirent * dent; (dent = readdir(dirp)) != NULL;) {
    const char *nm = dent->d_name; // The first time dent is uninitialized 

Since you do not have a valid file name the stream open will certainly fail.
Also you don't know whether opendir("."); fails or not.

Read salem c's 2.
Last edited on
@coder777

I appreciate your effort but your code is very unclear in how it should connect to mine, moreover, you are writing a function and I cannot have a function inside another one given the suitability of my c++ version.
May you please tell me explicitly how to implement the opening file line to my code?

Also, which one is c's 2?
@OP,

This is your 3rd thread on the same issue. People here have given you good advice about how to proceed. You responded with comments like "I asked for help, and not to be insulted" and begging us to write your code for you.

I cannot have a function inside another one given the suitability of my c++ version


Huh? I'm sure this statement means something to you, but it is nonsense to me. @coder777 did not define a function within another. And all versions of c++ have allowed one function to call another function. So I don't know what you are stating.

Also, which one is c's 2?


@coder777 said to read "salem c's" 2. This is the post with really good content that you decided not to read because you thought it was insulting. Go back and read it again with an open mind. If you were insulted by the term "dog food", I will hazard a guess that @salem c was referring to the horrific indentation that it possessed. I think "dog food" is a very kind description.
I appreciate your effort but your code is very unclear in how it should connect to mine
Does that mean you don't know what an if clause is?

Also, which one is c's 2?
->
salem c wrote:
2. Look where your closedir() is. Assuming success, you're only sending one image before it blows up in your face.
->Move closedir() out of the loop.
@doug
You responded with comments like "I asked for help, and not to be insulted" and begging us to write your code for you.

As you can tell, salem already wrote a whole code in another thread, but I still chose to stick to my own code and correct it with this forum's help. So the reality is quite the opposite of what you are claiming, and that's another insulting remark, for the records.



Huh? I'm sure this statement means something to you, but it is nonsense to me. @coder777 did not define a function within another. And all versions of c++ have allowed one function to call another function. So I don't know what you are stating.

Sorry, I misread those lines, my bad.

This is the post with really good content that you decided not to read because you thought it was insulting.

Another false statement.
I ignored it because this code is the same exact one as mine. Salem didn't change anything.
If I am mistaking, please tell me where they differ.

@coder777
I appreciate your effort but your code is very unclear in how it should connect to mine
Does that mean you don't know what an if clause is?

That's not what I said, I only asked how should I implement your lines of code to mine in order to make it work. I don't think I am asking for much, am I ?




ok, I implemented those lines myself, but is still not working.
The statement "can't open folder" is printed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
ifstream stream(folder, std::ios::in | std::ios::binary);
if(stream.is_open())
    {
vector<char> imageDataVec((istreambuf_iterator<char>(stream)), istreambuf_iterator<char>());
cout << "Size: " << imageDataVec.size() << " bytes";
long conv_num= htonl(imageDataVec.size());
//send(new_socket, &converted_number, sizeof(converted_number), 0);
//send(new_socket, &imageDataVec, imageDataVec.size() , 0);

size_t sent{};
while (sent < imageDataVec.size()) 
    {
 //   send(new_socket, &converted_number, sizeof(conv_num), 0);
    int nbytes = send(new_socket, &imageDataVec[sent], imageDataVec.size() - sent, 0);
    if (nbytes <= 0) {
        std::clog << "error: while sending image\n";
        break;
    
    sent += nbytes;
    cout<<nbytes<<"================"<<endl;
                        }
 
    }

}else
{cout<<"can't open folder"<<endl;}

}

Time for a new thread ... this one's arrived at the silly stage already.
And I'm all out of cutlery.

> The statement "can't open folder" is printed.
No shit - why do you think that might be?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  DIR *dirp = opendir(".");

  for (struct dirent * dent; (dent = readdir(dirp)) != NULL;) {
    const char *nm = dent->d_name;

    if (strcmp(nm, ".") == 0 || strcmp(nm, "..") == 0)
      continue;

    struct stat file_stats;
    if (stat(nm, &file_stats) == -1)
      perror(nm);
    else
      printf("%9u: %s\n", (unsigned) file_stats.st_size, nm);

    char folder[(unsigned) file_stats.st_size];

    sprintf(folder, "home/Desktop/pics/%s", nm);

Just throw all that folder crap in the bin and go straight to
 
ifstream stream(nm, std::ios::in | std::ios::binary);

That's not what I said, I only asked how should I implement your lines of code to mine in order to make it work. I don't think I am asking for much, am I ?
Yes, it's way too much. We are not here to do the work for you. If you're not willing to cooperate the thread will end. Period.

As salem suggested: I would first test the communication with a single file with well known content. Once that work you should do this with more...

Back to your problem: There are two possible reasons why the folder cannot be open:

1. It is a directory (check this)
2. opendir(...) opens the directory exclusively. I.e. forbids reading and writing within that directory.

To solve the latter problem there is scandir(...). Read:

https://linux.die.net/man/3/scandir

It provide the list of names without further readdir(...)
As you can tell, salem already wrote a whole code in another thread, but I still chose to stick to my own code and correct it with this forum's help.


So, to recap, you know how to do what you want to do, so there is no need to follow the forum's advice. But it doesn't work, so you ask the forum to solve the problem for you using the structure you want to use.

This reminds me of when I was in third grade. Our teacher instructed us to look up words in the dictionary. One word was "brake". My friends looked it up and found out it had to do with stopping a car. I wanted to be different, so I came up with a definition of "break". My teacher told me to look the word up and do it again. I came up with a different definition of "break". I did this another time or 2. Finally, I did it the way the teacher wanted, and realized that "brake" only referred to stopping. When I finally did it the way the teacher suggested, I got the right answer.

I haven't contributed a lot to this thread, but I'm done.
about your python code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
list_of_bytes=[]
for i in range(5*2): #¿do you have 10 images?
    data = s.recv(4) #reading the image size (checkout sizeof(long) in c++)
    if b'\x00\x00\x00\x00' in data: #¿why this line?
        continue

    data_bytes_amount = int.from_bytes(data, byteorder='big', signed=False)
    total_received = len(data) #should be 4, ¿may be less?

    if data_bytes_amount!=0:
        list_of_bytes.append(data_bytes_amount) #so here you have all the images sizes

#read all the images at once ¿?
pic_bytes=s.recv(sum(list_of_bytes))
#¿what are you doing here?
pic_bytes_amount=int.from_bytes(pic_bytes, byteorder='big', signed=False)
in your c++ code you send
[size1, image1, size2, image2, size3, image3, ...]
in your python code you expect
[size1, size2, size3, ..., sizen, imageall]

also, keep in mind that socket.recv may unblock without reading all the bytes so you need to replicate your send() loop on the receiving end
Last edited on
@ne555
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
list_of_bytes=[]
for i in range(5*2): #5 images, but the bytes in line 4, show after every image, so  is 5*2
    data = s.recv(4) #reading the image size (checkout sizeof(long) in c++)
    if b'\x00\x00\x00\x00' in data: #because it shows and counts as bytes, but I just want the image, so they have to be filtered out
        continue

    data_bytes_amount = int.from_bytes(data, byteorder='big', signed=False)
    total_received = len(data) #should be 4, ¿may be less?

    if data_bytes_amount!=0:
        list_of_bytes.append(data_bytes_amount) #so here you have all the images sizes

#read all the images at once ¿?   not my intention, trying to  change that. 
pic_bytes=s.recv(sum(list_of_bytes))
#¿what are you doing here?: turning bytes into  integers, maybe not necessary, but you never know
pic_bytes_amount=int.from_bytes(pic_bytes, byteorder='big', signed=False)


I am trying to receive all the bytes in a loop, but I would like to do a separation in the receiving part, according to the images individual sizes.
For instance, the first image is 3500 byes, and the second is 4000, the third is 2600 etc... how do I do this sort of separation in the loop?

@doug,
are you really comparing the definition of a word with the way different people code?
I sincerely hope that you have been drinking right before writing this nonsense, or else there is no excuse for it.
this reminds me of when I was in third grade.

given the temper tantrum you released, it sounds like you are still in third grade.

I haven't contributed a lot to this thread

So instead of spreading your toxic tone all over the place, you should perhaps find a forum that has nothing to do with coding. Possibly something child-friendly.
Last edited on
> because it shows and counts as bytes
I don't understand what you mean.
¿why are you receiving 0? ¿why are you discarding the 0?

when testing your code I noticed that when sending {1,2,3,4,5} was receiving {1,0,2,0,3,0,4,0,5,0}
¿who was inserting those 0?
in the server I had something like
1
2
3
4
for(int K=1; K<=5; ++K){
   long converted = htonl(K);
   send(new_socket, &converted, sizeof(converted), 0);
}
the problem was that in my system sizeof(converted) = sizeof(long) = 8
so was sending 8 bytes but the receiver expected 4
so changed the server to uint32_t converted; respecting the prototype of htonl()

> read all the images at once ¿?
>> not my intention, trying to change that.
this will read the size of one image, then that one image, then write that one image to disk
1
2
3
4
5
6
7
8
9
10
for i in range(5): #either pass the number of image at the beginning, or use some kind of sentinel to terminate
   data = s.recv(4)
   image_size = int.from_bytes(data, byteorder='big', signed=False)
   #image = s.recv(image_size)
   #because recv() may unblock before receiving all the bytes we need to loop
   image = []
   for K in range(image_size)
      pixel = s.recv(1)
      image.append(pixel)
   write('{}.jpeg'.format(i), image) #dunno which is the correct function 


the thing is, ¿what were you testing before? your server/client were not speaking the same language
it's like you want to prepare a cake so you read about open heart surgery
¿how did you expect that to work?

that's why we asked you to send just a string of characters
that's why we asked you to send a list of numbers
try simple things and make sure that works first


> ¿what are you doing here?
>> turning bytes into integers, maybe not necessary, but you never know
you are taking one image and converting to a number
¿does that make sense to you? don't just smash the keyboard when you code.
Pages: 12