How to send any file (image, exe) through UDP in C++? - c++

I'm trying to implement transmission of files through UDP protocol in C++.
What I've got is the server which can send a file requested by a client, but it only works for .txt files. When I try to do the same with image or executable, the transmission corrupts and the file is about 0 KB.
Server:
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#pragma comment(lib, "ws2_32.lib")
#define cipherKey 'S'
int const bufferSize = 512;
char buffer[bufferSize];
void clearBuf(char* b)
{
int i;
for (i = 0; i < bufferSize; i++)
b[i] = '\0';
}
char* notFound = "File not found.";
char Cipher(char ch)
{
return ch ^ cipherKey;
}
int sendFile(FILE* file, char* buffer, int s)
{
int i, len;
if (file == NULL)
{
strcpy(buffer, notFound);
len = strlen(notFound);
buffer[len] = EOF;
return 1;
}
char ch, ch2;
for (i = 0; i < s; i++)
{
ch = fgetc(file);
ch2 = Cipher(ch);
buffer[i] = ch2;
if (ch == EOF)
return 1;
}
return 0;
}
int main()
{
WSADATA wsaData;
int wynik_winsock = WSAStartup(MAKEWORD(2,2), &wsaData);
if(wynik_winsock != 0)
{
exit(1);
}
SOCKET socketServer;
socketServer = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(socketServer == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
char* ipAdd = "127.0.0.1";
int port = 1234;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ipAdd);
if(bind(socketServer, (SOCKADDR *)&server, sizeof(server)) == SOCKET_ERROR)
{
closesocket(socketServer);
WSACleanup();
exit(1);
}
std::cout << "Waiting." << std::endl;
SOCKADDR_IN client;
int len_client = sizeof(client);
FILE* file;
if(recvfrom(socketServer, buffer, bufferSize, 0, (SOCKADDR *)&client, &len_client) == SOCKET_ERROR) //Odbiór danych od clienta wraz z kontrolą błędów.
{
closesocket(socketServer);
WSACleanup();
exit(1);
}
else
{
file = fopen(buffer, "rb");
std::cout << "Filename: " << buffer << std::endl;
if(file == NULL)
{
std::cout << "Couldnt open a file." << std::endl;
}
else
{
while (true)
{
if(sendFile(file, buffer, bufferSize))
{
sendto(socketServer, buffer, bufferSize, 0, (SOCKADDR *)&client, len_client);
break;
}
sendto(socketServer, buffer, bufferSize, 0, (SOCKADDR *)&client, len_client);
clearBuf(buffer);
}
fclose(file);
}
}
closesocket(socketServer);
WSACleanup();
system("pause");
return 0;
}
Client:
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <string.h>
#pragma comment(lib, "ws2_32.lib")
#define cipherKey 'S'
int const bufferSize = 512;
char buffer[bufferSize];
void clearBuf(char* b)
{
int i;
for (i = 0; i < bufferSize; i++)
b[i] = '\0';
}
char Cipher(char ch)
{
return ch ^ cipherKey;
}
int recvFile(char* buffer, int s, FILE* file)
{
int i;
char ch;
for (i = 0; i < s; i++)
{
ch = buffer[i];
ch = Cipher(ch);
if (ch == EOF)
{
return 1;
}
else
{
fprintf(file, "%c", ch);
}
}
return 0;
}
int main()
{
WSADATA wsaData;
int wynik_winsock = WSAStartup(MAKEWORD(2,2), &wsaData);
if(wynik_winsock != 0)
{
exit(1);
}
SOCKET socketClient;
socketClient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(socketClient == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
char* ipAdd = "127.0.0.1";
int port = 1234;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ipAdd);
int serverSizeOf = sizeof(server);
std::cout << "Name of file to send: ";
std::cin >> buffer;
if(sendto(socketClient, buffer, bufferSize, 0, (SOCKADDR *)&server, serverSizeOf) == SOCKET_ERROR)
{
closesocket(socketClient);
WSACleanup();
exit(1);
}
FILE* file;
file = fopen(buffer, "ab");
while (true)
{
clearBuf(buffer);
if(recvfrom(socketClient, buffer, bufferSize, 0, (SOCKADDR *)&server, &serverSizeOf) == SOCKET_ERROR)
{
closesocket(socketClient);
WSACleanup();
exit(1);
}
if (recvFile(buffer, bufferSize, file))
{
break;
}
fclose(file);
}
closesocket(socketClient);
WSACleanup();
system("pause");
return 0;
}
To do what I said above, I used the tutorial: C program for file Transfer using UDP (Linux).
How can I adapt the code to send other files than .txt only? Thank you in advance.

As said in the comments above you need a data type where EOF has a different value from all other character values, char is inadequate in this respect, especially when you are dealing with binary data.
The following change should improve things
int sendFile(FILE* file, char* buffer, int s)
{
...
for (i = 0; i < s; i++)
{
int ch = fgetc(file);
if (ch == EOF)
return 1;
buffer[i] = Cipher(ch);
}
...

I've decided to change nearly everything in the original solution I tried to implement. The most important changes are reading file using fread and writing it using fwrite.
The file is send in parts of 512 bytes (or less) and those parts are counted in the variable.
If the file requested by a client doesn't exist on the server, special information is sent and the file created to save data is deleted.
Now the program works as expected even for executables and SHA256 of both files, original and received, are the same.
Server:
//SERVER
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <ctime>
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSADATA wsaData;
int winsock_result = WSAStartup(MAKEWORD(2,2), &wsaData);
if(winsock_result != 0)
{
exit(1);
}
SOCKET server_socket;
server_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(server_socket == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
char* ip_address = "127.0.0.1";
int port = 6666;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_address);
if(bind(server_socket,(SOCKADDR *)&server, sizeof(server)) == SOCKET_ERROR)
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
std::cout << "Waiting for data." << std::endl;
SOCKADDR_IN client;
int client_sizeof = sizeof(client);
int const buffer_size = 512;
char buffer[buffer_size];
if(recvfrom(server_socket, buffer, buffer_size, 0,(SOCKADDR *)&client, &client_sizeof) == SOCKET_ERROR)
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
else
{
FILE* file;
file = fopen(buffer, "rb");
std::cout << "Filename: " << buffer << std::endl;
if(file == NULL)
{
std::cout << "Couldn't open the file." << std::endl;
strcpy(buffer, "NOFILE");
if(sendto(server_socket, buffer, buffer_size, 0,(SOCKADDR *)&client, client_sizeof) == SOCKET_ERROR)
{
fclose(file);
closesocket(server_socket);
WSACleanup();
exit(1);
}
}
fseek(file, 0, SEEK_END);
int file_size = ftell(file);
size_t reading_size;
int part = 0;
const clock_t begin_time = clock();
while((part * buffer_size) < file_size)
{
fseek(file, (part * buffer_size), SEEK_SET);
reading_size = fread(buffer, 1, buffer_size, file);
if(sendto(server_socket, buffer, reading_size, 0,(SOCKADDR *)&client, client_sizeof) == SOCKET_ERROR)
{
fclose(file);
closesocket(server_socket);
WSACleanup();
exit(1);
}
part++;
}
std::cout << "Sent " << part << " parts of " << buffer_size << " bytes." << std::endl;
std::cout << "Time of sending file: " << float( clock () - begin_time ) / CLOCKS_PER_SEC << " seconds." << std::endl;
strcpy(buffer, "QUIT");
if(sendto(server_socket, buffer, buffer_size, 0,(SOCKADDR *)&client, client_sizeof) == SOCKET_ERROR)
{
fclose(file);
closesocket(server_socket);
WSACleanup();
exit(1);
}
fclose(file);
}
closesocket(server_socket);
WSACleanup();
system("pause");
return 0;
}
Client:
//CLIENT
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <string.h>
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSADATA wsaData;
int winsock_result = WSAStartup(MAKEWORD(2,2), &wsaData);
if(winsock_result != 0)
{
exit(1);
}
SOCKET client_socket;
client_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(client_socket == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
char* ip_address = "127.0.0.1";
int port = 6666;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_address);
int server_sizeof = sizeof(server);
int const buffer_size = 512;
char buffer[buffer_size];
std::cout << "Name of the requested file: ";
std::cin >> buffer;
char filename[buffer_size];
strcpy(filename, buffer);
if(sendto(client_socket, buffer, buffer_size, 0,(SOCKADDR *)&server, server_sizeof) == SOCKET_ERROR)
{
closesocket(client_socket);
WSACleanup();
exit(1);
}
FILE* file;
file = fopen(filename, "wb");
int received_size = 0;
while(true)
{
received_size = recvfrom(client_socket, buffer, buffer_size, 0,(SOCKADDR *)&server, &server_sizeof);
if(received_size == SOCKET_ERROR)
{
fclose(file);
closesocket(client_socket);
WSACleanup();
exit(1);
}
if(strcmp(buffer, "NOFILE") == 0)
{
std::cout << "The file does not exist on the server." << std::endl;
fclose(file);
remove(filename);
break;
}
else if(strcmp(buffer, "QUIT") == 0)
{
std::cout << "Transmission ended by the server." << std::endl;
break;
}
fwrite(buffer, sizeof(char), received_size, file);
}
fclose(file);
closesocket(client_socket);
WSACleanup();
system("pause");
return 0;
}

Related

accept socket errno 9 c++

New to socket programming, trying to implement a TCP server, but accept() returns -1 and errno = 9 (bad file descriptor). The problem arose after I introduced the accept() function in the freertos task. I really don’t understand what the problem is here, because before this my action everything worked, but I need to use the task.
#include "TCP.hpp"
#include <iostream>
#include <cmath>
#include <cerrno>
#include <cstring>
#include <clocale>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "freertos/queue.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>
#include "ping/ping_sock.h"
#include "errno.h"
static const char *TAG = "TCP";
QueueHandle_t TCP::xQueue1 = NULL;
ip_addr_t TCP::target_addr;
int TCP::ip_protocol;
int TCP::listen_sock;
sockaddr_in TCP::servaddr;
sockaddr_in TCP::cliaddr;
char TCP::addr_str[128];
char TCP::buf[128];
int TCP::sock;
TCP::Clbk_t TCP::clbk_tcp_recv = nullptr;
sockaddr_storage TCP::source_addr;
typedef struct
{
int len;
void * dataPtr;
}message;
void TCP::tcp_set_Clbk(Clbk_t clbk)
{
clbk_tcp_recv = clbk;
}
void TCP::tcp_create_server(sa_family_t serv_family, in_addr_t serv_addr, in_port_t serv_port)
{
int opt = 1;
struct sockaddr_in6 *servaddrPtr;
if (serv_family == AF_INET){
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_len = 24;
servaddr.sin_family = serv_family;
servaddr.sin_addr.s_addr = serv_addr;
servaddr.sin_port = htons(serv_port);
ip_protocol = IPPROTO_IP;
} else if (serv_family == AF_INET6){
servaddrPtr = (struct sockaddr_in6 *)&servaddr;
servaddrPtr->sin6_len = 24;
servaddrPtr->sin6_family = serv_family;
servaddrPtr->sin6_port = htons(serv_port);
ip_protocol = IPPROTO_IPV6;
}
ESP_LOGI(TAG, "Create socket...\n");
if ((listen_sock = socket(serv_family, SOCK_STREAM, ip_protocol)) < 0) {
ESP_LOGE(TAG, "socket not created\n");
}
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
ESP_LOGI(TAG, "Socket created");
int err = bind(listen_sock, (struct sockaddr *)&servaddr, sizeof(servaddr));
if (err != 0) {
ESP_LOGE(TAG, "Socket unable to bind errno %d", errno);
ESP_LOGE(TAG, "IPPROTO: %d", serv_family);
goto CLEAN_UP;
}
ESP_LOGI(TAG, "Socket bound, port %d", serv_port);
err = listen(listen_sock, 1);
if (err != 0) {
ESP_LOGE(TAG, "Error occurred during listen: errno %d", errno);
goto CLEAN_UP;
}
ESP_LOGI(TAG, "Soccket listening . . .");
xTaskCreate(tcp_listening_task, "tcp_listening_task", 4096, nullptr, 5, nullptr);
CLEAN_UP:
close(listen_sock);
}
void TCP::tcp_listening_task(void *arg)
{
int keepAlive = 1;
socklen_t addr_len = sizeof(source_addr);
ESP_LOGI(TAG, "Socket %d ",listen_sock);
for (;;) {
sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);
ESP_LOGI(TAG, "Socket %d ",sock);
if (sock < 0) {
ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
}
if (sock > 0) {
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(int));
if (source_addr.ss_family == PF_INET) {
inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);
}
else if (source_addr.ss_family == PF_INET6) {
inet6_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);
}
ESP_LOGI(TAG, "Socket %d accepted ip address: %s",sock, addr_str);
xTaskCreate(tcp_task_recv, "tcp_task_recv", 4096, nullptr, 5, nullptr);
}
}
}
void TCP::tcp_task_recv(void *arg)
{
int n;
int number_receiving = 0;
struct timeval tv;
tv.tv_sec = 1;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,(struct timeval *)&tv,sizeof(struct timeval));
ESP_LOGI(TAG,"server waiting message");
for (;;) {
n = recv(sock, (char *)buf, sizeof(buf), 0);
if (n < 0) {
ESP_LOGE(TAG, "Error occurred during receiving: errno %d", errno);
number_receiving++;
if (number_receiving == 10) {
number_receiving = 0;
}
}
else if (n == 0) {
ESP_LOGW(TAG, "Connection closed");
number_receiving = 0;
}
else {
if (clbk_tcp_recv != nullptr) clbk_tcp_recv(buf, n, (struct sockaddr *)&source_addr);
number_receiving = 0;
}
}
}
void TCP::tcp_sendd(void *data, uint32_t length)
{
static message msg;
xQueue1 = xQueueCreate(10, sizeof(message));
xTaskCreate(tcp_task_send, "udp_task_send", 4096, nullptr, 5, nullptr);
if(sock < 0){
ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
return;
}
if(xQueue1 == NULL){
ESP_LOGE(TAG, "queue is null");
return;
}
msg.dataPtr = data;
msg.len = length;
xQueueSend(xQueue1, (void *)&msg, portMAX_DELAY);
}
void TCP::tcp_task_send(void *arg)
{
message pxRxedMessage;
for(;;)
{
xQueueReceive(xQueue1, (void *)&pxRxedMessage, portMAX_DELAY);
int err = send(sock, pxRxedMessage.dataPtr, pxRxedMessage.len, 0);
if (err < 0){
ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
}
}
}
I tried to look for information on this issue, but since. I'm also new to c++ programming, nothing worked out
You should be passing the listen_sock as the arg parameter to tcp_listening_task(), rather than using a static class member, eg:
int listen_sock = socket(...);
...
xTaskCreate(tcp_listening_task, "tcp_listening_task", 4096, reinterpret_cast<void*>(listen_sock), 5, nullptr);
...
void TCP::tcp_listening_task(void *arg)
{
int listen_sock = reinterpret_cast<int>(arg);
...
close(listen_sock);
}
And especially the same with sock and tcp_task_recv() too, since your server is designed to handle multiple clients being connected simultaneously, which you can't handle with a single static sock variable:
int sock = accept(...);
...
xTaskCreate(tcp_task_recv, "tcp_task_recv", 4096, reinterpret_cast<void*>(sock), 5, nullptr);
...
void TCP::tcp_task_recv(void *arg)
{
int sock = reinterpret_cast<int>(arg);
...
close(sock);
}

How to receive multiple files through TCP and save them at the same time in C++?

I'm trying to create an app which would accept many connections from clients at the same time and it works for me, but it also should download those files at the same time. In this version of server, even if clients are connected simultaneously, files are written one by one.
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <ctime>
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSADATA wsaData;
int winsock_result = WSAStartup(MAKEWORD(2,2), &wsaData);
if(winsock_result != 0)
{
exit(1);
}
SOCKET server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(server_socket == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
int const max_clients = 100;
int client_socket[max_clients];
for (int i = 0; i < max_clients; i++)
{
client_socket[i] = 0;
}
char* ip_address = "127.0.0.1";
int port = 6666;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_address);
int server_sizeof = sizeof(server);
int opt = TRUE;
if( setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
if(bind(server_socket,(SOCKADDR *)&server, server_sizeof) == SOCKET_ERROR)
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
if(listen(server_socket, 5) == SOCKET_ERROR)
{
std::cout << "Nasluchiwanie portu nieudane." << std::endl;
}
else
{
std::cout << "Nasluchiwanie portu " << port << " udane." << std::endl << std::endl;
}
int const buffer_size = 512;
char buffer[buffer_size];
int max_socket_descriptor, socket_descriptor;
int downloaded_files = 1;
fd_set readfds;
while(true)
{
FD_ZERO(&readfds);
FD_SET(server_socket, &readfds);
max_socket_descriptor = server_socket;
for (int i = 0 ; i < max_clients ; i++)
{
socket_descriptor = client_socket[i];
if(socket_descriptor > 0)
{
FD_SET( socket_descriptor, &readfds);
}
if(socket_descriptor > max_socket_descriptor)
{
max_socket_descriptor = socket_descriptor;
}
}
if ((select( max_socket_descriptor + 1, &readfds, NULL, NULL, NULL) < 0) && (errno != EINTR))
{
std::cout << "Blad funkcji select." << std::endl;
}
if (FD_ISSET(server_socket, &readfds))
{
int new_sockfd;
if ((new_sockfd = accept(server_socket,(SOCKADDR *)&server, &server_sizeof)) == SOCKET_ERROR)
{
std::cout << "Otrzymanie deskryptora nieudane." << std::endl;
}
else
{
for (int i = 0; i < max_clients; i++)
{
if( client_socket[i] == 0 )
{
client_socket[i] = new_sockfd;
std::cout << "Dodawanie do listy socketow jako numer " << i << std::endl;
break;
}
}
}
}
for (int i = 0; i < max_clients; i++)
{
socket_descriptor = client_socket[i];
if (FD_ISSET( socket_descriptor, &readfds))
{
struct sockaddr_in client_address;
char filename[buffer_size];
std::stringstream ip_filename;
ip_filename << "plik" << downloaded_files << "_" << inet_ntoa(client_address.sin_addr);
strcpy(filename, ip_filename.str().c_str());
std::cout << "Nazwa pliku (IP klienta): " << filename << std::endl;
FILE* file;
file = fopen(filename, "wb");
const clock_t begin_time = clock();
int received_size;
do
{
memset(buffer, 0, buffer_size);
received_size = recv(socket_descriptor, buffer, buffer_size, 0);
if (received_size == 0 || received_size == -1)
{
break;
}
fwrite(buffer, sizeof(char), received_size, file);
}
while (received_size != 0);
fclose(file);
std::cout << "Czas wysylania pliku: " << float( clock () - begin_time ) / CLOCKS_PER_SEC << " sekund." << std::endl << std::endl;
closesocket(socket_descriptor);
client_socket[i] = 0;
downloaded_files++;
}
}
}
closesocket(server_socket);
WSACleanup();
system("pause");
return 0;
}
What should I do to make them write many at the same time? I've tried many modifications of the code above but every time I can't get wanted result.
For example:
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <ctime>
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSADATA wsaData;
int winsock_result = WSAStartup(MAKEWORD(2,2), &wsaData);
if(winsock_result != 0)
{
exit(1);
}
SOCKET server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(server_socket == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
int const max_clients = 100;
int client_socket[max_clients];
for (int i = 0; i < max_clients; i++)
{
client_socket[i] = 0;
}
char* ip_address = "127.0.0.1";
int port = 6666;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_address);
int server_sizeof = sizeof(server);
int opt = TRUE;
if( setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
if(bind(server_socket,(SOCKADDR *)&server, server_sizeof) == SOCKET_ERROR)
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
if(listen(server_socket, 5) == SOCKET_ERROR)
{
std::cout << "Nasluchiwanie portu nieudane." << std::endl;
}
else
{
std::cout << "Nasluchiwanie portu " << port << " udane." << std::endl << std::endl;
}
int const buffer_size = 512;
char buffer[buffer_size];
int max_socket_descriptor;
int downloaded_files = 1;
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(server_socket, &readfds);
max_socket_descriptor = server_socket;
while(true)
{
if ((select( max_socket_descriptor + 1, &readfds, NULL, NULL, NULL) < 0) && (errno != EINTR))
{
std::cout << "Blad funkcji select." << std::endl;
}
for (int i = 0 ; i < max_clients ; i++)
{
if(FD_ISSET(server_socket, &readfds))
{
int new_sockfd;
if ((new_sockfd = accept(server_socket,(SOCKADDR *)&server, &server_sizeof)) == SOCKET_ERROR)
{
std::cout << "Otrzymanie deskryptora nieudane." << std::endl;
}
else
{
for (int i = 0; i < max_clients; i++)
{
if( client_socket[i] == 0 )
{
client_socket[i] = new_sockfd;
FD_SET( client_socket[i], &readfds);
if(client_socket[i] > max_socket_descriptor)
{
max_socket_descriptor = client_socket[i];
}
std::cout << "Dodawanie do listy socketow jako numer " << i << std::endl;
break;
}
}
}
}
if(FD_ISSET(client_socket[i], &readfds))
{
struct sockaddr_in client_address;
char filename[buffer_size];
std::stringstream ip_filename;
ip_filename << "plik" << downloaded_files << "_" << inet_ntoa(client_address.sin_addr);
strcpy(filename, ip_filename.str().c_str());
std::cout << "Nazwa pliku (IP klienta): " << filename << std::endl;
FILE* file;
memset(buffer, 0, buffer_size);
int received_size;
received_size = recv(client_socket[i], buffer, buffer_size, 0);
if (received_size <= 0)
{
closesocket(client_socket[i]);
FD_CLR(client_socket[i], &readfds);
client_socket[i] = 0;
break;
}
else
{
file = fopen(filename, "ab");
fwrite(buffer, sizeof(char), received_size, file);
fclose(file);
}
downloaded_files++;
}
}
}
closesocket(server_socket);
WSACleanup();
system("pause");
return 0;
}
I thought about opening and closing those files every received packet and appending every packet to them, but I really don't have idea how to do it. The example of modified code was meant to do it, but it doesn't work.
I'm forbidden to use other processes and threads than the main one, so I'm kinda helpless now. Thanks for your help.
You have the basic loop with select in place, which is good.
accept is already (mostly) non-blocking. You just need to turn on non-blocking mode on the client sockets and then you'll be able to handle multiple client reads, writes and accepts in your main select loop.
You can have a vector of client-specific data per client, with each entry containing the client socket, the opened file and any other client-specific state.
After the accept, you create a new client entry and add it to the vector. Then in the main loop you do FD_SET for accept and all client's reads and writes. After the select, you inspect the the FD sets and handle them one by one. For best performance you will want your file I/O also in non-blocking mode, but for this assignment that's probably overkill.

Issue with C++ UDP Client Hanging Up

The project I am working on uses TCP and UDP to create a file transport protocol. The TCP connection generates a random port in which it returns to the client and the client then connects to the server on that port number using UDP. UDP is then used to transfer a text file four characters a time to the server and the server will send back the characters capitalized in which will then be displayed on the client. The issue is that the client is hanging up when waiting for the server to send back the capitalized version of the characters. I will leave the code below. The part of the code that is not working is commented out towards the end of the client and server files. Any help is appreciated!
Client Code
// Libraries
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <unistd.h>
using namespace std;
int main(int argc, char* argv[]) {
// Variables
int port = strtol(argv[2], NULL, 10);
string file = argv[3];
int r_port;
FILE* fp;
string fileString;
string dataBuffer;
int charCounter = 0;
char c;
// *** Declare TCP socket ***
int tcpsocket = 0;
tcpsocket = socket(AF_INET, SOCK_STREAM, 0);
if (tcpsocket == -1) {
cerr << "Can't create a socket";
return 1;
}
// Get host IP address
struct hostent *s;
s = gethostbyname(argv[1]);
// Setting destination info
struct sockaddr_in server;
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port);
bcopy((char *) s->h_addr, (char *) &server.sin_addr.s_addr, s->h_length);
// Connect to server
int connectRes = connect(tcpsocket, (sockaddr*)&server, sizeof(server));
if (connectRes == -1) {
cerr << "Can't connect to socket";
return 1;
}
// Sending data to server
char payload[512] = "117";
int sendRes = send(tcpsocket, payload, 512, 0);
if (sendRes == -1) {
cerr << "Could not send to server";
return 1;
}
// Receive r_port from server
memset(payload, 0, sizeof(payload));
recv(tcpsocket, payload, 512, 0);
r_port = strtol(payload, NULL, 10);
close(tcpsocket);
// *** Declare UDP socket ***
int udpsocket = 0;
udpsocket = socket(AF_INET, SOCK_DGRAM, 0);
if (udpsocket == -1) {
cerr << "Can't create a socket";
return 1;
}
// Get host IP address
s = gethostbyname(argv[1]);
// Setting destination info
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(r_port);
bcopy((char *) s->h_addr, (char *) &server.sin_addr.s_addr, s->h_length);
// File manipulation
fp = fopen(file.c_str(), "r");
while (c != EOF) {
c = fgetc(fp);
fileString += c;
charCounter++;
}
fclose(fp);
// UDP file transfer
for (int i = 4; i < 8; i++) {
dataBuffer += fileString[i];
}
socklen_t slen = sizeof(server);
memset(payload, 0, sizeof(payload));
strcpy(payload, dataBuffer.c_str());
sendRes = sendto(udpsocket, payload, 32, 0, (struct sockaddr *) &server, slen);
if (sendRes == -1) {
cerr << "Could not send to server";
return 1;
}
// Receive ack
// slen = sizeof(server);
// memset(payload, 0, sizeof(payload));
// recvfrom(udpsocket, payload, 32, 0, (sockaddr*)&server, &slen);
// cout << "Capitalized data: " << payload;
close(udpsocket);
return 0;
}
Server Code
// Libraries
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <cstdlib>
#include <time.h>
#include <ctype.h>
using namespace std;
// Variables
int r_port;
string fileData;
// Generate Random Port
int randomPort() {
srand(time(NULL));
return rand() % ((65535 - 1024) + 1) + 1024;
}
// Capitalization Function
string capitalize(char* payload) {
int i = 0;
char c;
string charArr;
while(payload[i]) {
c = payload[i];
charArr += toupper(c);
i++;
}
return charArr;
}
int main(int argc, char* argv[]) {
// Variables
int port = strtol(argv[1], NULL, 10);
// *** Declare TCP socket ***
int tcpsocket = 0;
tcpsocket = socket(AF_INET, SOCK_STREAM, 0);
if (tcpsocket == -1) {
cerr << "Can't create a socket";
return -1;
}
// Receive data
struct sockaddr_in server;
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(tcpsocket, (struct sockaddr *) &server, sizeof(server)) == -1) {
cerr << "Can't bind to IP/Port";
return -2;
}
if (listen(tcpsocket, SOMAXCONN) == -1) {
cerr << "Can't listen";
return -3;
}
struct sockaddr_in client;
char payload[512];
socklen_t clen = sizeof(client);
int clientSocket = accept(tcpsocket, (sockaddr*)&client, &clen);
if (clientSocket == -1) {
cerr << "Problem with client connecting";
return -4;
}
recv(clientSocket, payload, 512, 0);
// Check client data
if (strtol(payload,NULL,10) == 117) {
r_port = randomPort();
cout << "Handshake detected. Selected the random port " << r_port << "\n";
}
else {
cout << "Error occurred\n";
}
// Return random port
memset(payload, 0, sizeof(payload));
sprintf(payload,"%ld",r_port);
int sendRes = send(clientSocket, payload, 512, 0);
if (sendRes == -1) {
cerr << "Could not send to server\n";
return 1;
}
close(clientSocket);
close(tcpsocket);
// *** Declare UDP socket ***
int udpsocket = 0;
udpsocket = socket(AF_INET, SOCK_DGRAM, 0);
if (udpsocket == -1) {
cerr << "Can't create a socket";
return -1;
}
// Receive data
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(r_port);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(udpsocket, (struct sockaddr *) &server, sizeof(server)) == -1) {
cerr << "Can't bind to IP/Port";
return -2;
}
clen = sizeof(client);
memset(payload, 0, sizeof(payload));
recvfrom(udpsocket, payload, 32, 0, (sockaddr*)&client, &clen);
fileData = capitalize(payload);
cout << "Payload: " << fileData << "\n";
// Send ack
// socklen_t slen = sizeof(server);
// memset(payload, 0, sizeof(payload));
// strcpy(payload, fileData.c_str());
// sendRes = sendto(udpsocket, payload, 32, 0, (struct sockaddr *) &server, slen);
// if (sendRes == -1) {
// cerr << "Could not send to server";
// return 1;
// }
close(udpsocket);
return 0;
}
ssize_t sendto(**int sockfd**, const void *buf, size_t len, int flags,
const struct **sockaddr *dest_addr**, socklen_t addrlen);
Reference : https://linux.die.net/man/2/sendto
Your destination address should be : (sockaddr *) &client

simple multicast app not working on different computer on the same network

If I launch 2 instances of the code below in the same computer the multicast works fine.
If I launch it on a different computer in the same network I won't receive anything.
Any idea what could be wrong? This code should compile as is.
I am testing on win10 but I get similar results when I run this on linux.
#include "pch.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include "winsock2.h"
#include <iostream>
#include <conio.h>
#include <thread>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
char mcastGroup[] = "224.1.2.3";
int mcastPort = 5435;
int CreateSocket()
{
return socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
}
void JoinGroup(int sck)
{
struct ip_mreq grp;
grp.imr_multiaddr.s_addr = inet_addr(mcastGroup);
grp.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(sck, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&grp, sizeof(grp)) < 0)
{
printf("Error in joining group\n");
closesocket(sck);
exit(1);
}
}
int receiver()
{
int sck = CreateSocket();
int reuse = 1;
if (setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
{
perror("Socket reuse address error\n");
closesocket(sck);
exit(1);
}
JoinGroup(sck);
struct sockaddr_in lclSck;
memset((char *)&lclSck, 0, sizeof(lclSck));
lclSck.sin_family = AF_INET;
lclSck.sin_port = htons(mcastPort);
lclSck.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sck, (struct sockaddr*)&lclSck, sizeof(lclSck)))
{
perror("Error in binding socket\n");
closesocket(sck);
exit(1);
}
while (1)
{
int blen;
char buf[1024];
blen = sizeof(buf);
memset(buf, 0, blen);
struct sockaddr_in addrin;
int addrinlen = sizeof(addrin);
memset(&addrin, 0, sizeof(addrin));
int res = recvfrom(sck, buf, blen, 0, (sockaddr *)&addrin, &addrinlen);
if (res<0)
{
printf("Message read error\n");
closesocket(sck);
exit(1);
}
else
{
printf(": %s\n", buf);
}
}
return 0;
}
int sender()
{
int sck = CreateSocket();
struct in_addr lclInterface;
lclInterface.s_addr = htonl(INADDR_ANY);
if (setsockopt(sck, IPPROTO_IP, IP_MULTICAST_IF, (char *)&lclInterface, sizeof(lclInterface)) < 0)
{
printf("Local interface error\n");
exit(1);
}
else
{
printf("Local interface set\n");
}
u_char ttl = 5;
setsockopt(sck, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl));
while (1)
{
int blen;
char buf[1024];
blen = sizeof(buf);
memset(buf, 0, blen);
for (int i = 0; i < 100; i++)
{
fgets(buf, blen, stdin);
sockaddr_in grpSck;
memset((char *)&grpSck, 0, sizeof(grpSck));
grpSck.sin_family = AF_INET;
grpSck.sin_port = htons(mcastPort);
grpSck.sin_addr.s_addr = inet_addr(mcastGroup);
if (sendto(sck, buf, blen, 0, (struct sockaddr*)&grpSck, sizeof(grpSck)) < 0)
{
printf("Error in sending message");
}
}
}
return 0;
}
int main()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
std::thread t1([&] { receiver(); return 0; });
sender();
WSACleanup();
}
This code should work, the problem was that I was using IP_MULTICAST_IF, that forces to use a network interface different from the default one. In case one needs to use such a thing I was able to get the multicast working by following
Thanks to Remy Lebeau advice, that is to make sure you are binding the sockets to IPs that are in the same network.
Here is working code the code:
#ifdef WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#endif
#include <thread>
char mcastGroup[] = "224.1.2.3";
int mcastPort = 5435;
void PrintAddrIn(sockaddr_in addr_in)
{
char str[255];
inet_ntop(AF_INET, &addr_in.sin_addr, (char *)str, sizeof(str));
printf("%s", str);
}
int receiver(int sck)
{
while (1)
{
char buf[1024];
memset(buf, 0, sizeof(buf));
struct sockaddr_in addrin;
socklen_t addrinlen = sizeof(addrin);
memset(&addrin, 0, sizeof(addrin));
int res = recvfrom(sck, buf, sizeof(buf), 0, (sockaddr *)&addrin, &addrinlen);
if (res<0)
{
printf("Message read error\n");
exit(1);
}
else
{
PrintAddrIn(addrin); printf(": %s\n", buf);
}
}
return 0;
}
int sender(int sck)
{
while (1)
{
sockaddr_in grpSck;
memset((char *)&grpSck, 0, sizeof(grpSck));
grpSck.sin_family = AF_INET;
grpSck.sin_port = htons(mcastPort);
grpSck.sin_addr.s_addr = inet_addr(mcastGroup);
for (int i = 0; i < 100; i++)
{
char buf[1024];
fgets(buf, sizeof(buf), stdin);
if (sendto(sck, buf, strlen(buf), 0, (struct sockaddr*)&grpSck, sizeof(grpSck)) < 0)
{
printf("Error in sending message");
exit(1);
}
}
}
return 0;
}
int main()
{
#ifdef WIN32
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
int sck = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
// Set reuse
//
int reuse = 1;
if (setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
{
perror("Socket reuse address error\n");
exit(1);
}
else
{
printf("Socket reuse address successfull\n");
}
// Join mcast group
//
struct ip_mreq grp;
grp.imr_multiaddr.s_addr = inet_addr(mcastGroup);
grp.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(sck, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&grp, sizeof(grp)) < 0)
{
printf("Error in joining group\n");
exit(1);
}
else
{
printf("Group joined successfully\n");
}
// Bind socket
//
struct sockaddr_in lclSck;
memset((char *)&lclSck, 0, sizeof(lclSck));
lclSck.sin_family = AF_INET;
lclSck.sin_port = htons(mcastPort);
lclSck.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sck, (struct sockaddr*)&lclSck, sizeof(lclSck)))
{
perror("Error in binding socket\n");
exit(1);
}
else
{
printf("Socket binding successfull\n");
}
u_char ttl = 5;
setsockopt(sck, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl));
std::thread t1([&] { receiver(sck); return 0; });
sender(sck);
#ifdef WIN32
WSACleanup();
#endif
}

application/zip winsock c++

I'm trying to make a GET url request, response content type is "application/zip," but I'm having trouble outputting the content to an appropriate/readable zip file, here is my code, as you can tell, I'm trying to write out to 2 different files, neither are working, both are unreadable as zip files:
bool ionMyPlugin::downloadRact(int goodsId) {
goodsId = 36028;
WSADATA wsaData;
SOCKET Socket;
SOCKADDR_IN SockAddr;
int lineCount = 0;
int rowCount = 0;
struct hostent *host;
locale local;
char buffer[10000];
int i = 0;
int nDataLength;
string website_HTML;
// website url
string url = "eihome.eihoo.com";// / api ? mod = rayvr&app = apigoods&act = index&store_id = 34837 & secret_key = 8d410f7007b47e76c227cfa8c282c5f5&add_time = 1474877868 & company = eihome%E6%B5 % 8B % E8%AF % 95 % E4%BC % 81 % E4%B8 % 9A & sign = fd53cce56c4eb88e356d58f19c337e79";
string url2 = "?mod=rayvr&app=apigoods&act=download&store_id=34837&goods_id=36010&secret_key=8d410f7007b47e76c227cfa8c282c5f5&add_time=1474877868&company=eihome%E6%B5%8B%E8%AF%95%E4%BC%81%E4%B8%9A&sign=fd53cce56c4eb88e356d58f19c337e79";// +goodsId;
//HTTP GET
string get_http = "GET /" + url2 + " HTTP/1.1\r\nHost: " + url + "\r\nConnection: close\r\n\r\n";
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){
cout << "WSAStartup failed.\n";
system("pause");
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
host = gethostbyname(url.c_str());
SockAddr.sin_port = htons(80);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0){
cout << "Could not connect";
system("pause");
}
// send GET / HTTP
send(Socket, get_http.c_str(), strlen(get_http.c_str()), 0);
ofstream myfile;
fstream myfile2("myfile2.zip", ios::out | ios::binary);
myfile.open("example.zip", std::ios_base::binary);
// recieve html
int countWS = 0;
while ((nDataLength = recv(Socket, buffer, 10000, 0)) > 0){
int i = 0;
while (buffer[i]){//buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r'){
myfile << buffer[i];
myfile2.write(reinterpret_cast<char *> (&buffer[i]), sizeof(buffer[i]));
website_HTML += buffer[i];// >> 8);
//website_HTML += ((buffer[i] << 8) >> 8);
i += 1;
if (i >= nDataLength)
break;
}
}
closesocket(Socket);
WSACleanup();
return false;
}
You may check this example :
#include <string>
#include <stdio.h>
#include <winsock2.h>
#define BUFFER_LEN (4096)
using std::string;
int main(int argc, char **argv)
{
HANDLE fhand;
string request;
int sendret;
int iRecv;
int iResponseLength=0;
int offset;
DWORD dw;
string res2;
char recvBuffer[BUFFER_LEN]={0};
string response;
const char lb[]="\r\n\r\n";
const char http[]="http\x3a//";
const char snsn[]="%s\n";
bool error1=false;
bool error2=false;
bool error3=false;
int len3=strlen(argv[3]);
printf(snsn,"\n-=[ httpget v1.0 by Avery Tarasov");
printf(snsn,"-=[ Email: c0ldshadow#deeptide.com");
printf(snsn,"-=[ Web: www.DeepTide.com");
printf(snsn,"-=[ Dedicated to my fiance, Ostine!\n");
printf(snsn,"Example usage: httpget theserver.com /somefolder/somefile.zip C:\\savehere.zip");
if(argc!=4)
{
printf(snsn,"\nInvalid usage");
goto cleanup;
}
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{
printf(snsn,"\nError initializing Winsock 2.2");
goto cleanup;
}
error1=true;
if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
{
printf(snsn,"\nWinsock 2.2 not available");
goto cleanup;
}
printf(snsn,"\nWinsock 2.2 initialized via wsa2_32.dll");
struct hostent *h;
struct sockaddr_in sa;
SOCKET server1;
h=gethostbyname(argv[1]);
if(h==0)
{
printf(snsn,"\ngethostbyname() failed");
goto cleanup;
}
printf("%s","\nHost lookup succeeded for ");
printf(snsn,argv[1]);
memcpy((char *)&sa.sin_addr,(char *)h->h_addr,sizeof(sa.sin_addr));
sa.sin_family=h->h_addrtype;
sa.sin_port=htons(80);
server1=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(server1==INVALID_SOCKET)
{
printf(snsn,"\nsocket() failed");
goto cleanup;
}
error1=false;
error2=true;
if(connect(server1,(struct sockaddr *)&sa,sizeof(sa))<0)
{
printf(snsn,"\nconnect() failed");
goto cleanup;
}
printf("%s","\nNow connected to ");
printf("%s",argv[1]);
printf(snsn," via port 80");
request+="GET ";
request+=argv[2];
request+=" HTTP/1.0";
request+=&lb[2];
request+="Host: ";
request+=argv[1];
request+=lb;
printf(snsn,"\nHTTP request constructed successfully:\n");
printf(snsn,request.c_str());
sendret=send(server1,request.c_str(),request.length(),0);
if(sendret==-1)
{
printf(snsn,"send() failed");
goto cleanup;
}
printf(snsn,"Successfully sent HTTP request to the server");
printf(snsn,"\nWaiting for download to complete");
fhand=CreateFile(argv[3],GENERIC_WRITE,FILE_SHARE_READ,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
if(fhand==INVALID_HANDLE_VALUE)
{
printf(snsn,"\nCreateFile() failed");
goto cleanup;
}
error2=false;
error3=true;
while((iRecv=recv(server1,recvBuffer,BUFFER_LEN-1,0))>0)
{
/*
char hex[5];
string packet;
packet.reserve(5*iRecv);
printf(snsn,"\n");
printf("%s","Receiving ");
printf("%d",iRecv);
printf(snsn," byte packet:\n");
for(int i=0;i<iRecv;++i)
{
wsprintf(hex,"%02x",(unsigned char)recvBuffer[i]);
packet.append(hex);
printf("%s ",hex);
}
*/
response.append(recvBuffer,iRecv);
iResponseLength+=iRecv;
ZeroMemory(recvBuffer,BUFFER_LEN);
}
if(iRecv==SOCKET_ERROR)
{
printf(snsn,"\n\nrecv() failed");
}
offset=response.find(lb)+4;
if(offset!=string::npos)
{
printf("%s","\n\nFile starts at offset ");
printf("%d\n",offset);
printf(snsn,"\nInitial response from server:\n");
for(int j=0;j<offset;++j)
{
printf("%c",response[j]);
}
res2.assign(response,offset,response.size());
if(WriteFile(fhand,res2.data(),res2.size(),&dw,0)==0)
{
printf(snsn,"\nWriteFile() failed");
goto cleanup;
}
else
{
printf("%s","\nFile successfully downloaded and saved to ");
printf(snsn,argv[3]);
}
}
cleanup:
if(error1)
{
WSACleanup();
}
if(error2)
{
WSACleanup();
closesocket(server1);
}
if(error3)
{
WSACleanup();
closesocket(server1);
CloseHandle(fhand);
}
return 0;
}