I am trying to upload files to the server, but they always come corrupted, the program is very simple, only serves to transfer files between client and server.
I need assistance in this code, for fix the problem.
and improve it.
SERVER
int Socket_Manip::FILE_UPLOAD() {
//get file size.
iResult = recv(ClientSocket, GotFileSize, LENGTH, 0);
if (iResult == 0)
{
closesocket(ClientSocket);
WSACleanup();
return 1;
}
else if (iResult < 0) {
closesocket(ClientSocket);
WSACleanup();
return 1;
}
//start manip download
long FileSize = atoi(GotFileSize);
long SizeCheck = 0;
char* mfcc;
FILE *fp = fopen("C::\\Users\\Server\\Downloads\\transfer.zip", "wb");
if (fp == NULL)
{
closesocket(ClientSocket);
WSACleanup();
return 1;
}
if (FileSize > 1499) {
mfcc = (char*)malloc(1500);
while (FileSize > SizeCheck){
int Received = recv(ClientSocket, mfcc, 1500, 0);
if (Received == 0)
{
break;
}
else if (Received < 0) {
closesocket(ClientSocket);
WSACleanup();
return 1;
}
SizeCheck += Received;
fwrite(mfcc, 1, Received, fp);
fflush(fp);
}
} else
{
mfcc = (char*)malloc(FileSize + 1);
int Received = recv(ClientSocket, mfcc, FileSize, 0);
fwrite(mfcc, 1, Received, fp);
fflush(fp);
}
fclose(fp);
free(mfcc);
}
CLIENT SENDER
int File_Transfer_Manip() {
FILE *File;
char *Buffer;
unsigned long Size;
File = fopen("C:\\Users\\r4minux\\Downloads\\upload.zip", "rb");
if (!File)
{
printf("Error file\n");
return 1;
}
fseek(File, 0, SEEK_END);
Size = ftell(File);
fseek(File, 0, SEEK_SET);
Buffer = new char[Size];
fread(Buffer, Size, 1, File);
char cSize[MAX_PATH];
sprintf(cSize, "%i", Size);
fclose(File);
iResult = send(ConnectSocket, cSize, MAX_PATH, 0); // File size
if (iResult == SOCKET_ERROR) {
printf("send erroR: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
getchar();
return 1;
}
int Offset = 0;
while (Offset < Size)
{
int Amount = send(ConnectSocket, Buffer + Offset, Size - Offset, 0);
if (Amount <= 0)
{
std::cout << "Error: " << WSAGetLastError() << std::endl;
break;
}
else
{
Offset += Amount;
}
}
// cleanup
free(Buffer);
}
TCP is a byte stream. It has no concept of message boundaries. You are not making sure that send() is actually sending everything you give it, or that recv() is reading everything you ask it to. They CAN return fewer bytes. You have to account for that.
Try this instead:
SERVER:
int readBytes(SOCKET s, void *buffer, int buflen)
{
int total = 0;
char *pbuf = (char*) buffer;
while (buflen > 0)
{
int iResult = recv(s, pbuf, buflen, 0);
if (iResult < 0)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
{
// optionally use select() to wait for the
// socket to have more bytes to read before
// calling recv() again...
continue;
}
printf("recv error: %d\n", WSAGetLastError());
return SOCKET_ERROR;
}
else if (iResult == 0)
{
printf("disconnected\n");
return 0;
}
else
{
pbuf += iResult;
buflen -= iResult;
total += iResult;
}
}
return total;
}
int Socket_Manip::FILE_UPLOAD()
{
//start download
FILE *fp = fopen("C::\\Users\\Server\\Downloads\\transfer.zip", "wb");
if (fp == NULL)
{
printf("Error creating file\n");
closesocket(ClientSocket);
WSACleanup();
return 1;
}
//get file size.
unsigned long FileSize;
int iResult = readBytes(ClientSocket, &FileSize, sizeof(FileSize));
if (iResult <= 0)
{
fclose(fp);
closesocket(ClientSocket);
WSACleanup();
return 1;
}
FileSize = ntohl(FileSize);
char mfcc[1024];
while (FileSize > 0)
{
int Received = readBytes(ClientSocket, mfcc, min(sizeof(mfcc), FileSize));
if (Received <= 0)
{
fclose(fp);
closesocket(ClientSocket);
WSACleanup();
return 1;
}
if (fwrite(mfcc, 1, Received, fp) != Received)
{
printf("Error writing file\n");
fclose(fp);
closesocket(ClientSocket);
WSACleanup();
return 1;
}
FileSize -= Received;
}
fflush(fp);
fclose(fp);
return 0;
}
CLIENT
int sendBytes(SOCKET s, void *buffer, int buflen)
{
int total = 0;
char *pbuf = (char*) buffer;
while (buflen > 0)
{
int iResult = send(s, pbuf, buflen, 0);
if (iResult < 0)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
{
// optionally use select() to wait for the
// socket to have more space to write before
// calling send() again...
continue;
}
printf("send error: %d\n", WSAGetLastError());
return SOCKET_ERROR;
}
else if (iResult == 0)
{
printf("disconnected\n");
return 0;
}
else
{
pbuf += iResult;
buflen -= iResult;
total += iResult;
}
}
return total;
}
int File_Transfer_Manip()
{
char Buffer[1024];
FILE *fp = fopen("C:\\Users\\r4minux\\Downloads\\upload.zip", "rb");
if (!fp)
{
printf("Error opening file\n");
return 1;
}
fseek(fp, 0, SEEK_END);
unsigned long FileSize = ftell(fp);
fseek(fp, 0, SEEK_SET);
unsigned long tmpFileSize = htonl(FileSize);
int iResult = sendBytes(ConnectSocket, &tmpFileSize, sizeof(tmpFileSize));
if (iResult <= 0)
{
fclose(fp);
closesocket(ConnectSocket);
WSACleanup();
getchar();
return 1;
}
while (FileSize > 0)
{
long Size = fread(Buffer, 1, min(sizeof(Buffer), FileSize), fp);
if (Size <= 0)
{
printf("Error reading file\n");
fclose(fp);
closesocket(ConnectSocket);
WSACleanup();
getchar();
return 1;
}
if (sendBytes(ConnectSocket, Buffer, Size) != Size)
{
fclose(fp);
closesocket(ConnectSocket);
WSACleanup();
getchar();
return 1;
}
FileSize -= Size;
}
fclose(fp);
return 0;
}
Related
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;
}
When i send the file to the client it gets corrupted, and with a size in bytes higher.
I have a version of this server running on Windows and works perfectly,but I'm not having the same result on Linux.
The file size on disk may be the error in time to send the size in bytes to the client that runs on another platform?
fread function is being used correctly?
an expert can analyze and help find the error?
LINUX SERVER SIDE
// FUNCTION TO UPLOAD A FILE TO CLIENT WINDOWS
int Socket_Setup::FILE_UPLOAD(int iD, std::string DIR_UPLOAD)
{
char Block[1024];
long FileSize;
int BytesRead;
fp = fopen(DIR_UPLOAD.c_str(), "rb");
if (!fp)
{
errno_message.append((char*)strerror(errno));
FUNCTION_LOG(errno_message);
return 1;
}
fseek(fp, 0, SEEK_END);
FileSize = ftell(fp);
rewind(fp);
long Size_Send = htonl(FileSize);
Total = FileSize;
// Sending the file size to the Windows Client
iResult = send(client[iD].socket, (const char*)&Size_Send, sizeof(long), 0);
if (iResult <= 0)
{
errno_message.append((char*)strerror(errno));
FUNCTION_LOG(errno_message);
return 1;
}
// LOOP TO SEND FILE
while (FileSize > 0)
{
BytesRead = fread(Block, 1, sizeof(Block), fp);
if (BytesRead <= 0)
{
errno_message.append((char*)strerror(errno));
FUNCTION_LOG(errno_message);
fclose(fp);
return 1;
}
if (send(client[iD].socket, Block, BytesRead, 0) != BytesRead)
{
errno_message.append((char*)strerror(errno));
FUNCTION_LOG(errno_message);
fclose(fp);
return 1;
}
FileSize -= BytesRead;
}
fclose(fp);
return 0;
}
WINDOWS CLIENT SIDE:
int readBytes(SOCKET s, void *buffer, int buflen)
{
int total = 0;
char *pbuf = (char*)buffer;
while (buflen > 0)
{
int iResult = recv(s, pbuf, buflen, 0);
if (iResult < 0)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
continue;
return SOCKET_ERROR;
}
else if (iResult == 0)
return 0;
else
{
pbuf += iResult;
buflen -= iResult;
total += iResult;
}
}
return total;
}
// FUNCTION TO DOWNLOAD FILE FROM SERVER
int Remote_Manip::FILE_DOWNLOAD(std::string directory, Socket_Setup &socket_setup)
{
unsigned long FileSize;
char mfcc[65535];
File = fopen(directory.c_str(), "wb");
if (File == NULL)
{
closesocket(socket_setup.ConnectSocket);
WSACleanup();
return 1;
}
// Receiving file size from server
int iResult = readBytes(socket_setup.ConnectSocket, &FileSize, sizeof(FileSize));
if (iResult <= 0)
{
fclose(File);
closesocket(socket_setup.ConnectSocket);
WSACleanup();
return 1;
}
FileSize = ntohl(FileSize);
// LOOP TO RECEIVING FILE
while (FileSize > 0)
{
int Received = recv(socket_setup.ConnectSocket, mfcc, sizeof(mfcc),0);
if (Received <= 0)
{
fclose(File);
closesocket(socket_setup.ConnectSocket);
WSACleanup();
return 1;
}
if (fwrite(mfcc, 1, Received, File) != Received)
{
fclose(File);
closesocket(socket_setup.ConnectSocket);
WSACleanup();
return 1;
}
FileSize -= Received;
}
fflush(File);
fclose(File);
return 0;
}
I'm a new comer in this stackoverflow.
I successfully sent a file.txt and received it . And I want to send the file through a socket periodically and receive it periodically, too. This is a server client program. Client should send the data and server should receive it with an interval time.
Anyone know how to do this? I used this way:
need to call a function at periodic time intervals in c++
Problem is the file is not sent.
Here is my client code :
void Inwinsock(){
WSAStartup(MAKEWORD(2,2), &winsock);
if (LOBYTE(winsock.wVersion) != 2 || HIBYTE(winsock.wVersion) != 2 ) {
WSACleanup();
}
}
void ClientSock() {
clientSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ZeroMemory(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(6091);
}
int _tmain(int argc, _TCHAR* argv[])
{
Inwinsock();
ClientSock();
start:
if (connect(clientSock, (sockaddr*)&addr, sizeof(addr)) < 0 ) {
Sleep(5000);
goto start;
}
printf("Socket Connected ......... \n");
FILE *File;
char *Buffer;
unsigned long Size;
File = fopen("B:\Filesend.txt","rb");
if(!File){
printf("", WSAGetLastError());
goto END;
}
printf("File open ok ! \n");
fseek(File,0,SEEK_END);
Size = ftell(File);
fseek(File,0,SEEK_SET);
printf("file size succeed...\n");
Buffer = (char*) malloc (Size+1);
fread(Buffer,Size,1,File);
char cisi[10];
sprintf(cisi, "%i", Size);
fclose(File);
printf("sending data....\n");
send(clientSock,cisi,10,0); //file size sent
send(clientSock,Buffer,Size,0); // File Binary sent
free(Buffer);
printf("sending finished....\n");
END:
closesocket(clientSock);
WSACleanup();
getchar();
return 0;
system("PAUSE");
}
and here are my server code :
void iniSocket() {
WSAStartup(MAKEWORD(2,2), &winsock);
if (LOBYTE(winsock.wVersion) != 2 || HIBYTE(winsock.wVersion) != 2) {
WSACleanup();
}
}
void opSock(){
servSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ZeroMemory(&addr , sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(6091);
bind(servSocket, (sockaddr*)&addr, sizeof(addr));
}
void sockList(){
if (listen(servSocket, 5) == SOCKET_ERROR ) {
printf("listen error %d\n", WSAGetLastError());
}else
{
printf("listen succeed....\n");
}
}
void receive() {
if(recv(ClientAcc,Filesize,10,0)){
Size = atoi((const char*)Filesize);
printf("File size : %d\n",Size);
}
Buffer = (char*)malloc(Size + 1);
int file_dit, total_file = 0 ;
while(total_file < Size)
{
ZeroMemory(Buffer, Size);
if((file_dit = recv(ClientAcc,Buffer,Size,0)) < 0)
{
goto END;
}
else
{
total_file += file_dit;
File = fopen("fileReceived.txt", "wb");
fwrite((const char*)Buffer,1,file_dit,File);
fclose(File);
Sleep(1000);
}
END:
printf("File received \n");
free(Buffer);
closesocket(ClientAcc);
WSACleanup();
getchar();
}
}
int _tmain(int argc, _TCHAR* argv[])
{
while(1)
{
iniSocket();
opSock();
sockList();
if (ClientAcc = accept(servSocket, (sockaddr*)&incommingAddress, &addresslen))
{
char *ClientIP = inet_ntoa(incommingAddress.sin_addr);
int ClientPort = ntohs (incommingAddress.sin_port);
printf("Client connected ....\n" );
printf("IP : %s:%d\n ", ClientIP, ClientPort);
receive();
}
}
return 0;
system("PAUSE");
}
For the periodic part, you could take everything between the start: and END: labels, and put it in a new function, say, sendMyFile();
Then in the client's _tmain(), between the start: and END: labels,
while (1)
{
sendMyFile();
Sleep( 30000 ); // The interval is 30,000.
}
There are certainly better, more sophisticated ways to do something periodically, but this is a good, simple, educational approach.
I'm trying to create a server that talks with 2 clients, 1 in each time. After the talking with one client, the server sends a message to both clients.
I found a basic code of a server, and I tried to upgrade it to accept multiple number of connections, and I saw 2 ways of it : threads, or doing array of sockets, but I couldn't understand it.
Can someone explain me how to use threads and give examples please?
This is the code :
int main()
{
WSADATA WsaDat;
if (WSAStartup(MAKEWORD(2, 2), &WsaDat) != 0)
{
std::cout << "WSA Initialization failed!\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (Socket == INVALID_SOCKET)
{
std::cout << "Socket creation failed.\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
SOCKADDR_IN serverInf;
serverInf.sin_family = AF_INET;
serverInf.sin_addr.s_addr = INADDR_ANY;
serverInf.sin_port = htons(8888);
if (bind(Socket, (SOCKADDR*)(&serverInf), sizeof(serverInf)) == SOCKET_ERROR)
{
std::cout << "Unable to bind socket!\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
listen(Socket, 1);
SOCKET TempSock = SOCKET_ERROR;
while (TempSock == SOCKET_ERROR)
{
std::cout << "Waiting for incoming connections...\r\n";
TempSock = accept(Socket, NULL, NULL);
}
// If iMode!=0, non-blocking mode is enabled.
u_long iMode = 1;
ioctlsocket(Socket, FIONBIO, &iMode);
Socket = TempSock;
std::cout << "Client connected!\r\n\r\n";
// Main loop
for (;;)
{
char *szMessage = "Welcome to the server!\r\n";
send(Socket, szMessage, strlen(szMessage), 0);
int nError = WSAGetLastError();
if (nError != WSAEWOULDBLOCK&&nError != 0)
{
std::cout << "Winsock error code: " << nError << "\r\n";
std::cout << "Client disconnected!\r\n";
// Shutdown our socket
shutdown(Socket, SD_SEND);
// Close our socket entirely
closesocket(Socket);
break;
}
Sleep(1000);
}
WSACleanup();
system("PAUSE");
return 0;
}
To do so you need one server socket and a clientsocket array like this:
SERVER:
ACCEPT:
int clientsock[2];
minsocks = 0;
numsocks = 2;
while(minsock < numsocks)
{
clientsock[minsock] = accept(serversock,
(struct sockaddr *) &clientaddr,
(socklen_t *)&clientaddrlen);
minsock++;
}
RECIEVE:
char message[6];
int data;
int limit = 6;
for(int i = 0; i < NUMSOCK; i++)
{
int in = recv(clientsock[i], &message[index], limit, 0);
if(in > 0)
{
index += in;
limit -= in;
}
else if ( in == 0 )
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
}
This should be a good beginning for you to start with.
Threads - C version
pthread_t sniffer_thread;
if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0)
{
perror("could not create thread");
return 1;
}
//Now join the thread , so that we dont terminate before the thread
//pthread_join( sniffer_thread , NULL);
puts("Handler assigned");
}
/*
* This will handle connection for each client
* */
void *connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = *(int*)socket_desc;
int read_size;
char *message , client_message[2000];
while(in != 0)
{
int in = recv(socket_desc, &client_message[index], limit, 0);
if(in > 0)
{
index += in;
limit -= in;
}
else
printf("recv failed: %d\n", WSAGetLastError());
}
//Free the socket pointer
free(socket_desc);
return 0;
}
I have one socket, which act as server while executed and response some results.
First I compile it: g++ -o a daemon.cpp dictionary.cpp -lpthread c++11
then execute : ./a
Now it will listen for the request on some port.
I want that one I create the object file a, it should not manually executed. Rather work as daemon file, which continously listen for the request.
I saw using fork() id something can be done. But I could not correct place in my below code:
variable declation I have removed:
using namespace std;
using namespace boost;
void *SocketHandler(void *);
int main(int argv, char **argc)
{
pthread_t thread_id = 0;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if (hsock == -1)
{
printf("Error initializing socket %dn", errno);
goto FINISH;
}
p_int = (int *) malloc(sizeof(int));
*p_int = 1;
if ((setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char *) p_int, sizeof(int)) == -1)
|| (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char *) p_int, sizeof(int)) == -1))
{
printf("Error setting options %dn", errno);
free(p_int);
goto FINISH;
}
free(p_int);
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(hsock, (sockaddr *) & my_addr, sizeof(my_addr)) == -1)
{
fprintf(stderr, "Error binding to socket, make sure nothing else is listening on this port %dn", errno);
goto FINISH;
}
if (listen(hsock, 10) == -1)
{
fprintf(stderr, "Error listening %dn", errno);
goto FINISH;
}
//Now lets do the server stuff
addr_size = sizeof(sockaddr_in);
int pid;
pid_t pid=fork();
if(pid<0)
exit(EXIT_FAILURE);
else if(pid>0){
//this is parent process, exit now
exit(EXIT_SUCCESS); // again no goto
}
else{
//this is child or daemon
unmask();
pid_t childid = setsid();
while (true)
{
printf("waiting for a connectionn\n");
csock = (int *) malloc(sizeof(int));
if ((*csock = accept(hsock, (sockaddr *) & sadr, &addr_size)) != -1)
{
printf("---------------------nReceived connection from %s\n", inet_ntoa(sadr.sin_addr));
pthread_create(&thread_id, 0, &SocketHandler, (void *) csock);
pthread_detach(thread_id);
}
else
{
fprintf(stderr, "Error accepting %dn", errno);
}
sleep(60);
}
FINISH:
;
}
void *SocketHandler(void *lp)
{
char *ch;/* stores references to 50 words. */
char *ch2[50] = { 0 };
char *excluded_string;
char *word;
if ((bytecount = recv(*csock, (char*) rcv.c_str(), rcv.length(), 0)) == -1)
{
fprintf(stderr, "Error receiving data %d \n", errno);
goto FINISH;
}
do
{
bytesReceived = recv(*csock, buffer.data(), buffer.size(), 0);
// append string from buffer.
if ( bytesReceived == -1 )
{
fprintf(stderr, "Error receiving data %d \n", errno);
goto FINISH;
}
else
rcv.append( buffer.cbegin(), buffer.cend() );
} while ( bytesReceived == MAX_BUF_LENGTH );
word = strtok(& rcv[0]," ");
while (word!= NULL)
{
skp = BoyerMoore_skip(word, strlen(word) );
if(skp != NULL)
{
i++;
printf("this also \n");
word = strtok(NULL, " ");
continue;
}
printf("\n Word %s \n",word);
bfr << word << " ";
result_string = bfr.str();
word = strtok(NULL, " ");
j++;
}
ss<<result_string;
while (std::getline(ss, item, ' '))
{
writable.push_back(item);
}
for (std::vector < std::string >::iterator it = writable.begin(); it != writable.end(); it++)
++src[*it];
std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()), mytransform);
rec=dst.begin();
for (auto it = dst.begin(); it != dst.end(); ++it)
std::cout << it->second << ":" << it->first << std::endl;
if ((bytecount = send(*csock, (char *)ar, i *sizeof(int), 0)) == -1)
{ // Here we cant send lenth-1. It consider exact
fprintf(stderr, "Error sending data %d\n", errno);
goto FINISH;
}
FINISH:
free(csock);
return 0;
}
#include <sys/types.h>
#include <unistd.h>
pid_t pid=fork();
if(pid<0)
exit(EXIT_FAILURE); //see no goto
else if(pid>0){
//this is parent process, exit now
exit(EXIT_SUCCESS); // again no goto
}
else{
//this is child or daemon
unmask();
pid_t childid = setsid();
while(true){
myTask(); //Run the Process
sleep(60);
}
}
Ok I studied your program and made changes. This is how your code in main should look like.
using namespace std;
using namespace boost;
#define CHECK_THROW(condtion, code) if(condition) throw code
void *SocketHandler(void *);
int OpenSockets();
int main(int argv, char **argc)
{
try{
pid_t pid = fork();
CHECK_THROW(pid<0, -5);
if(pid==0)
{
//this is child or daemon
mode_t oldMask, newMask;
oldMask=unmask(newMask);
pid_t childid = setsid();
int hsock = OpenSocket();
CHECK_THROW(listen(hsock, 10) == -1, -4);
addr_size = sizeof(sockaddr_in);
while (true)
{
printf("waiting for a connectionn\n");
csock = (int *) malloc(sizeof(int));
*csock = accept(hsock, (sockaddr *) & sadr, &addr_size);
CHECK_THROW(*csock!=-1, -7);
printf("---------------------nReceived connection from %s\n", inet_ntoa(sadr.sin_addr));
pthread_t thread_id = pthread_create(&thread_id, 0, &SocketHandler, (void *) csock);
pthread_detach(thread_id);
}
}
}
catch(int ierror)
{
switch(ierror)
{
case -4: fprintf(stderr, "Error listening %dn", errno); break;
case -7: fprintf(stderr, "Error accepting %dn", errno); break;
}
}
}
int OpenSockets()
{
// Create your socket and return the socket handle from this function
}
void *SocketHandler(void *lp){ /*blah blah */ }