L'envoi de l'Image (JPEG) par Socket en C Linux
Je suis en train d'écrire un petit programme en C pour être en mesure de transférer un fichier d'image entre deux ordinateurs (de serveur à client linux en cours d'exécution) à l'aide de sockets TCP/IP, mais il semble y avoir une erreur que mon image s'affiche sur les autres côtés corrompu.
Le code de mon serveur est en tant que tel:
#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<iostream>
#include<fstream>
#include<errno.h>
using namespace std;
int send_image(int socket){
FILE *picture;
int size, read_size;
char send_buffer[10240], verify;
picture = fopen("2.jpg", "r");
printf("Getting Picture Size\n");
if(picture == NULL) {
printf("Error Opening Image File");
}
fseek(picture, 0, SEEK_END);
size = ftell(picture);
fseek(picture, 0, SEEK_SET);
//Send Picture Size
printf("Sending Picture Size\n");
write(socket, (void *)&size, sizeof(int));
if(read_size = read(socket, &verify , sizeof(char)) < 0) {
puts("\nError Receiving Verification");
}
if(verify == '1'){
printf("5\n");
//Send Picture as Byte Array
printf("Sending Picture as Byte Array\n");
while(!feof(picture)) {
//Read from the file into our send buffer
read_size = fread(send_buffer, 1, sizeof(send_buffer)-1, picture);
//Send data through our socket
write(socket, send_buffer, read_size);
//Wait for the verify signal to be received
while(read(socket, &verify , sizeof(char)) < 0);
if(verify != '1') {
printf("Error Receiving the Handshake signal\n %s",&verify);
}
verify = '';
//Zero out our send buffer
bzero(send_buffer, sizeof(send_buffer));
}
}
}
int main(int argc , char *argv[])
{
int socket_desc , new_socket , c, read_size,buffer = 0;
struct sockaddr_in server , client;
char *readin;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8889 );
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("bind failed");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
if((new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c))){
puts("Connection accepted");
}
fflush(stdout);
if (new_socket<0)
{
perror("Accept Failed");
return 1;
}
send_image(new_socket);
close(socket_desc);
fflush(stdout);
return 0;
}
Le code côté client qui reçoit les données en tant que telle:
#include<stdio.h>
#include<string.h> //strlen
#include<sys/socket.h>
#include<sys/ioctl.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<iostream>
#include<errno.h>
using namespace std;
//This function is to be used once we have confirmed that an image is to be sent
//It should read and output an image file
int receive_image(int socket){
int buffersize = 0, recv_size = 0,size = 0, read_size, write_size;
char imagearray[10241],verify = '1';
FILE *image;
//Find the size of the image
read(socket, &size, sizeof(int));
//Send our verification signal
write(socket, &verify, sizeof(char));
//Make sure that the size is bigger than 0
if(size <= 0 ){
printf("Error has occurred. Size less than or equal to 0\n");
return -1;
}
image = fopen("2.jpg", "w");
if( image == NULL) {
printf("Error has occurred. Image file could not be opened\n");
return -1;
}
//Loop while we have not received the entire file yet
while(recv_size < size) {
ioctl(socket, FIONREAD, &buffersize);
//We check to see if there is data to be read from the socket
if(buffersize > 0 ) {
if(read_size = read(socket,imagearray, buffersize) < 0){
printf("%s", strerror(errno));
}
//Write the currently read data into our image file
write_size = fwrite(imagearray,1,(buffersize), image);
if(write_size != buffersize) {
printf("write and buffersizes wrong");
}
if(read_size !=write_size) {
printf("error in read write");
}
//Increment the total number of bytes read
recv_size += read_size;
//Send our handshake verification info
write(socket, &verify, sizeof(char));
}
}
fclose(image);
printf("Image successfully Received!\n");
return 1;
}
int main(int argc , char *argv[])
{
int socket_desc;
struct sockaddr_in server;
char *parray;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1) {
printf("Could not create socket");
}
memset(&server,0,sizeof(server));
server.sin_addr.s_addr = inet_addr("10.42.0.1");
server.sin_family = AF_INET;
server.sin_port = htons( 8889 );
//Connect to remote server
if (connect(socket_desc , (struct sockaddr *)&server , sizeof(server)) < 0) {
cout<<strerror(errno);
close(socket_desc);
puts("Connect Error");
return 1;
}
puts("Connected\n");
receive_image(socket_desc);
close(socket_desc);
return 0;
}
Quelqu'un peut-il me donner un coup de main? Je ne peux pas voir la figure de cette erreur pour la vie de moi.
EDIT: j'ai changé le fwrites et freads retour régulier d'écriture et de lecture, et il envoie toujours une image endommagée
Vous n'avez pas besoin de
Avez-vous vérifié que chaque individu read_size correspondent à chaque write_size?
Double Possible de Envoyer et Recevoir un fichier dans le support de la programmation sous Linux en C/C++ (GCC/G++)
ioctl
et FIONREAD
; laisse-bloc si il n'y a pas encore de données. Ce n'est pas comme vous êtes en train de faire quelque chose d'autre dans le temps de le dire.Avez-vous vérifié que chaque individu read_size correspondent à chaque write_size?
Double Possible de Envoyer et Recevoir un fichier dans le support de la programmation sous Linux en C/C++ (GCC/G++)
OriginalL'auteur user1721182 | 2013-03-16
Vous devez vous connecter pour publier un commentaire.
Vous avez un certain nombre de problèmes:
"rb"
pour la lecture,"wb"
pour l'écriture), et non pas par défaut en mode texte. Sur Windows (et tous les autres systèmes qui ne de fin de ligne de la traduction), la stdio bibliothèque convertit Epa (octets 0x0A) dans CRLF paires (deux octets 0x0D 0x0A) lors de l'écriture, et il n'a l'inverse de la traduction lors de la lecture. Pour les non-texte, des données comme les fichiers JPEG, ce qui corrompt les données.send()
/write()
renvoie une valeur positive, alors que le nombre d'octets ont été reçus par les autres pairs.send()
/write()
peut pas envoyer toutes les données que vous lui demandez, il peut faire une partielle envoyer. Si cela se produit, vous devez continuer d'essayer d'envoyer le reste de la mémoire tampon dans une boucle.sizeof(char)
est garantie 1 par la norme du langage C, il y a rarement besoin de diresizeof(char)
quand à la place de votre code sera beaucoup plus clair sans qu'ilioctl
pour déterminer la quantité de données qui peuvent être lues sans blocage parce que vous êtes juste en boucle à nouveau votre code va tourner à 100% de CPU alors qu'il n'y a pas de données disponibles. Il suffit de laisser leread()
bloc d'appel. Si vous exécutez ce code sur un ordinateur portable, votre batterie va merci.ntohl(3)
ethtonl(3)
des fonctions pour effectuer ces conversions pour les 4 octets de valeurs.#include <unistd.h>
, alors vous n'avez pas à ouvrir les fichiers avec"rb"
et"r"
est très bien.Pour la partie client du code où vous l'avez mentionné, il devient partielle lit, c'est mon code n'est déjà prendre soin de cela? J'ai de la lecture en tant que nombre d'octets disponibles et puis l'écriture du fichier, le nombre d'octets renvoyés à partir de la fonction de lecture, puis en boucle jusqu'à ce qu'il a écrit le nombre d'octets égal à la taille du fichier.
Aussi cette image du programme de transfert est utilisé uniquement pour un client et un serveur qui va être exécuter Ubuntu n'est donc pas l'ouverture du fichier en mode binaire inutiles?
recommandez-vous de C ou de C++ pour écrire du code socket?
OriginalL'auteur Adam Rosenfield