UDP Sender program verification - c++

I have wrote a simple program that is supposed to send UDP Packages with changing length. The sizes of UDP packets can change anytime.
The user can input through command line the port number and the minimum and maximum length of the message. At the first 32 bits of the payload is the UDP Packet Number.
I used the sendto() function and I am receiving a valid return number but when I try to verify it using a UDP Server program (for example SocketTest) I cannot seeany data on the other end.
Following is my code :
#define DEFAULT_PORT 355
int Port = DEFAULT_PORT; // Port to send data to
int Max_Length = 100, Min_Length = 8; //default values
static const char alphanum[] =
"0123456789"
"!##$%^&*"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
int stringLength = sizeof(alphanum);
char genRandom()
{
return alphanum[rand() % stringLength];
}
void usage()
{
cout << "-m:int Define minimum UDP packet size" << endl;
cout << " -M:int Define maximum UDP packet size" << endl;
cout << " -p:int Define remote port" << endl;
}
void ValidateArgs(int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++)
{
if ((argv[i][0] == '-'))
{
switch (argv[i][1])
{
case 'm':
if (strlen(argv[i]) > 3) {
Min_Length = (double)atoi(&argv[i][3]);
}
break;
case 'M':
if (strlen(argv[i]) > 3) {
Max_Length = (double)atoi(&argv[i][3]);
}
break;
case 'p':
if (strlen(argv[i]) > 3) {
Port = atoi(&argv[i][3]);
}
break;
default:
usage();
break;
}
}
}
}
int main(int argc, char **argv)
{
sockaddr_in my_addr;
ValidateArgs(argc, argv);
WSADATA wsd;
int Result = WSAStartup(MAKEWORD(2, 2), &wsd);
if (Result != NOERROR) {
cout << "WSAStartup Failed!" << endl;
exit(0);
}
SOCKET sock;
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == INVALID_SOCKET) {
cout << "Socket Failer with error: " << WSAGetLastError() << endl;
WSACleanup();
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = inet_addr("192.68.0.31");
my_addr.sin_port = htons((short)Port);
string data = "";
/*Get a Random String Length*/
random_device seeder;
int UDP_Packet_number = 1;
string buffer_data;
mt19937 engine(seeder());
uniform_int_distribution<int> dist(Min_Length, Max_Length);// user input from command line
int StrLen = dist(engine);
while (true) {
/*Get aRandom String*/
for (int i = 0; i < StrLen; ++i)
{
data += genRandom();
}
srand(time(0));
StrLen = dist(engine);
char numbr_pkg[4];
numbr_pkg[0] = (UDP_Packet_number >> 24) & 0xff;
numbr_pkg[1] = (UDP_Packet_number >> 16) & 0xff;
numbr_pkg[2] = (UDP_Packet_number >> 8) & 0xff;
numbr_pkg[3] = UDP_Packet_number & 0xff;
/*First 32 Bits is the packet Number*/
for (int i = 0; i < 4; i++) {
buffer_data += numbr_pkg[i];
}
buffer_data += data;
data = "";
int result = sendto(sock, buffer_data.c_str(), buffer_data.length(), 0, (SOCKADDR *)&my_addr, sizeof(my_addr));
//cout << result << " " << buffer_data.length() << endl;
buffer_data = "";
UDP_Packet_number++;
}
return 0;
}
Can you please tell me what am I doing wrong? I am trying to find a solution for a long time.

Related

Сommunicate server client C++

I am writing a network program in C ++. How it works:
The server streams video for the client in real time.
The client receives the video data.
I tried to set up sending and receiving messages (right during streaming). For this, I started the video in a separate thread.
Messages from the client to the server reach the server without any problems. But if you send messages from the server to the client, then firstly the video itself changes, and some kind of garbage is displayed.
How it works (no)
I understand that this is due to the fact that the client is constantly receiving messages (vide). But is it possible to somehow solve this problem?
Server code
#include "server.h"
int Server::open()
{
WORD DLLVersion = MAKEWORD(2, 1);
if (WSAStartup(DLLVersion, &wsaData) != 0)
{
std::cout << "Error" << std::endl;
exit(1);
}
int sizeofaddr = sizeof(addr);
addr.sin_addr.s_addr = inet_addr(addrss);
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
server = socket(AF_INET, SOCK_STREAM, NULL);
bind(server, (SOCKADDR*)&addr, sizeof(addr));
listen(server, SOMAXCONN);
std::cout << "Listening..." << std::endl;
client = accept(server, (SOCKADDR*)&addr, &sizeofaddr);
if (client == 0) {
std::cout << "Error #2\n";
}
else {
std::cout << "Client Connected!\n";
}
}
int Server::sendData(const char *buffer, int len)
{
return send(client, buffer, len, NULL);
}
int Server::recvData(char *buffer, int len)
{
return recv(client, buffer, len, NULL);
}
int Server::close()
{
closesocket(server);
std::cout << "Server is closed" << std::endl;
return 0;
}
Server main
#include "server.h"
#include "opencv2/core/core.hpp"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2\video\background_segm.hpp"
#include <opencv2\video\tracking.hpp>
#include <Windows.h>
#include <thread>
#include <string>
#define FRAME_WIDTH 640
#define FRAME_HEIGHT 480
#define CLIENT_CLOSE_CONNECTION_SYMBOl '#'
cv::Mat cameraFeed;
int height, width, IM_HEIGHT, IM_WIDTH, imgSize;
bool is_client_connection_close(const char *msg)
{
for (int i = 0; i < strlen(msg); ++i)
{
if (msg[i] == CLIENT_CLOSE_CONNECTION_SYMBOl)
{
return true;
}
}
return false;
}
void VideoSender(Server server)
{
cv::VideoCapture cap(0);
while (true)
{
cv::Mat frame, image;
if (!cap.read(cameraFeed))
{
std::cout << "Video dont work" << std::endl;
break;
}
height = cameraFeed.rows;
width = cameraFeed.cols;
IM_HEIGHT = FRAME_HEIGHT;
IM_WIDTH = FRAME_WIDTH;
resize(cameraFeed, cameraFeed, cv::Size(IM_WIDTH, IM_HEIGHT));
imgSize = cameraFeed.total()*cameraFeed.elemSize();
server.sendData(reinterpret_cast<char*>(cameraFeed.data), imgSize);
imshow("Video_sending", cameraFeed);
char button = cv::waitKey(10);
if (button == 'q')
{
std::cout << "Stop sending video data..." << std::endl;
cap.release();
cv::destroyWindow("Video_sending");
server.close();
break;
}
}
}
int main(int argc, char* argv[])
{
Server server;
server.open();
std::thread th_video(VideoSender, server);
while (true)
{
//sending message
std::string msg1;
std::getline(std::cin, msg1);
int msg_size1 = msg1.size();
server.sendData((char*)&msg_size1, sizeof(int));
server.sendData(msg1.c_str(), msg_size1);
//receive_message
int msg_size;
server.recvData((char*)&msg_size, sizeof(int));
char *msg = new char[msg_size + 1];
msg[msg_size] = '\0';
server.recvData(msg, msg_size);
std::cout << "Message from client: " << msg
<< " (size: " << msg_size << ")"
<< std::endl;
delete[] msg;
}
system("pause");
return 0;
}
Client code
#include "client.h"
int Client::open()
{
WORD DLLVersion = MAKEWORD(2, 1);
if (WSAStartup(DLLVersion, &wsaData) != 0) {
std::cout << "Error" << std::endl;
exit(1);
}
int sizeofaddr = sizeof(addr);
addr.sin_addr.s_addr = inet_addr(addrs);
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
server = socket(AF_INET, SOCK_STREAM, NULL);
if (connect(server, (SOCKADDR*)&addr, sizeof(addr)) != 0) {
std::cout << "Error: failed connect to server.\n";
return 1;
}
std::cout << "Connected!\n";
}
int Client::sendData(const char * buffer, int len)
{
return send(server, buffer, len, NULL);
}
int Client::recvData(char *buffer, int len)
{
return recv(server, buffer, len, NULL);
}
int Client::close()
{
closesocket(server);
std::cout << "Server is closed" << std::endl;
return 0;
}
Client main
#include "client.h"
#include "opencv2/core/core.hpp"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2\video\background_segm.hpp"
#include <opencv2\video\tracking.hpp>
#include <Windows.h>
#include <string>
#include <thread>
#pragma warning(disable: 4996)
#define FRAME_WIDTH 640
#define FRAME_HEIGHT 480
int imgSize;
int bytes = 0;
bool running = true;
int msg_size;
void VideoReceiver(Client client)
{
while (running)
{
int IM_HEIGHT = FRAME_HEIGHT;
int IM_WIDTH = FRAME_WIDTH;
cv::Mat img = cv::Mat::zeros(FRAME_HEIGHT, FRAME_WIDTH, CV_8UC3);
imgSize = img.total()*img.elemSize();
const int ah = 921600;
char sockData[ah];
for (int i = 0; i < imgSize; i += bytes)
if ((bytes = client.recvData(sockData + i, imgSize - i)) == 0)
std::cout << "WTF" << std::endl;
int ptr = 0;
for (int i = 0; i < img.rows; ++i)
for (int j = 0; j < img.cols; ++j)
{
img.at<cv::Vec3b>(i, j) = cv::Vec3b(sockData[ptr + 0], sockData[ptr + 1], sockData[ptr + 2]);
ptr = ptr + 3;
}
cv::namedWindow("Reveived_video", cv::WINDOW_AUTOSIZE);
imshow("Reveived_video", img);
char button = cv::waitKey(10);
if (button == 'q')
{
std::cout << "Stop reveiving video data..." << std::endl;
cv::destroyWindow("Reveived_video");
client.close();
break;
}
}
}
void message_sendind(Client client)
{
while (true)
{
//receiv message
int msg_size;
client.recvData((char*)&msg_size, sizeof(int));
char *msg = new char[msg_size + 1];
msg[msg_size] = '\0';
client.recvData(msg, msg_size);
std::cout << "Message from server: " << msg
<< " (size: " << msg_size << ")"
<< std::endl;
delete[] msg;
//sending message
//std::string msg1;
//std::getline(std::cin, msg1);
//int msg_size1 = msg1.size();
//client.sendData((char*)&msg_size1, sizeof(int));
//client.sendData(msg1.c_str(), msg_size1);
}
}
int main(int argc, char* argv[])
{
Client client;
client.open();
std::thread th_video(VideoReceiver, client);
while (true)
{
//receiv message
int msg_size;
client.recvData((char*)&msg_size, sizeof(int));
char *msg = new char[msg_size + 1];
msg[msg_size] = '\0';
client.recvData(msg, msg_size);
std::cout << "Message from server: " << msg
<< " (size: " << msg_size << ")"
<< std::endl;
delete[] msg;
//sending message
std::string msg1;
std::getline(std::cin, msg1);
int msg_size1 = msg1.size();
client.sendData((char*)&msg_size1, sizeof(int));
client.sendData(msg1.c_str(), msg_size1);
}
system("pause");
return 0;
}

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.

How to access array at the server end of tcp/ip socket

I'm new to tcp socket with c++. I am trying to send a int array over the socket. I write my own client and socket(Both run on winOS). To make I can receive the int array type, I set the recvbuffer as int[] type and force it change to char inside the recv() function. This is part of the code of server:
int recvbuf[6];
and
iResult = recv(ClientSocket, (char *)&recvbuf, recvbuflen, 0);
The result is good, I can print out all the six numbers, which means my client works well. HOWEVER, when I switch the server to another one, which was built-in a sdk and running on linux, I can no longer access those numbers.
For the sdk, I have a I/O looks like this:
typedef BYTE char
unsigned int getData(BYTE * data, unsigned int len)
{
if (_dataFlag == 1)
{
if (len <= DATA_LENGTH)
{
memcpy(data, _receivedData, len);
_dataFlag = 0;
return len;
}
else
{
memcpy(data, _receivedData, DATA_LENGTH);
_dataFlag = 0;
return DATA_LENGTH;
}
}
return 0;
}
The way I access the _socketData is:
iResult = _tcpSocket.getData(_socketData, MSG_LEN);
int *ptr = (int *)&_socketData;
And use ptr[i] (i = 0 ... 5) to access the numbers. But it doesn't work, I don't get what I want. Could you guys please solve my problem, thx.
There is code how I send int array thru Client:
while (1)
{
ifstream infile;
infile.open(open_path);
if (!infile)
cout << "error" << endl;
string str;
double temp;
int length;
int array[6];
cout << "store to vector" << endl;
vector<double> ve;
while (infile >> temp)
{
ve.push_back(temp);
}
for (int i = 0; i < ve.size(); i++)
{
array[i] = ve[i] * 10000;
}
iResult = send(ConnectSocket, (char*)array, (int)sizeof(array), 0);
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
else {
cout << "success" << endl;
Sleep(500);
}
}

What is causing a C++ Buffer Overrun error with fprintf?

I am trying to set up a Client, Router, Server in C++ with sockets and UDP using GoBackN windowing. I'm not sure why I'm getting a buffer overrun error in Client::write_log(), at the fprintf() line.
Main run() function
void Client::run()
{
srand ( time(NULL) );
//socket data types
SOCKET client_socket; // Client socket
SOCKADDR_IN sa_out; // fill with server info, IP, port
char buffer[RAWBUF_SIZE]; // Buffer
WSADATA wsadata; // WSA connection
char router[11]; // Host data
char cusername[128], filename[128], direction[3]; // Other header data
DWORD dwusername = sizeof(cusername); // Retains the size of the username
char trace_data[128];
FILE* logfile = fopen("client.log", "w");
try
{
if (WSAStartup(0x0202,&wsadata)!=0)
{
throw "Error in starting WSAStartup";
}
else
{
/* Display the wsadata structure */
cout<< endl
<< "wsadata.wVersion " << wsadata.wVersion << endl
<< "wsadata.wHighVersion " << wsadata.wHighVersion << endl
<< "wsadata.szDescription " << wsadata.szDescription << endl
<< "wsadata.szSystemStatus " << wsadata.szSystemStatus << endl
<< "wsadata.iMaxSockets " << wsadata.iMaxSockets << endl
<< "wsadata.iMaxUdpDg " << wsadata.iMaxUdpDg << endl << endl;
}
client_socket = open_port(PEER_PORT2);
prompt("Enter the router hostname: ",router);
sa_out = prepare_peer_connection(router, ROUTER_PORT2);
prompt("Enter a filename: ",filename); // Retrieve a filename from the client
prompt("Direction of transfer [get|put]: ", direction); // Retrieve a transfer direction
// Make sure the direction is one of get or put
if(!strcmp(direction,GET) || !strcmp(direction,PUT))
{
// Retrieve the local user name
GetUserName(cusername, &dwusername);
int selected = rand() % 256;
int received, verify;
int client_num = 0; // Client packet number
int server_num = 0; // Server packet number
int progress = 0;
int rcv;
cout << "Starting packet ID negotiation..." << endl;
while(1)
{
// Send a random number to the server
if(progress < 1)
{
memset(buffer, 0, sizeof(buffer));
sprintf(buffer,"RAND %d",selected);
cout << "Sending " << buffer << endl;
if((rcv = send_safe(client_socket, sa_out, buffer, RAWBUF_SIZE, 200)) == 201)
{
progress = 1;
}
else if(rcv != 200)
{
continue;
}
// Finally wait for a response from the server with the number
if(recv_safe(client_socket, sa_out, buffer, RAWBUF_SIZE, 100) == 100)
{
cout << "Received " << buffer << endl;
sscanf(buffer,"RAND %d %d",&verify,&received);
}
else
continue;
progress = 1;
}
// Send acknowledgement to the server along with our random number
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "RAND %d", received);
cout << "Sending " << buffer << endl;
if(send_safe(client_socket, sa_out, buffer, RAWBUF_SIZE, 201) != 201)
{
progress = 0;
continue;
}
break;
}
client_num = selected % WINDOW_SIZE + 1;
server_num = received % WINDOW_SIZE + 1;
cout << "Negotiated server start " << server_num << " and client start " << client_num << endl;
sprintf(trace_data, "Negotiated srv %d and cli %d", server_num, client_num);
write_log(logfile, cusername, trace_data);
// Send client headers
sprintf(buffer, HEADER, cusername, direction, filename);
while((rcv = send_safe(client_socket,sa_out,buffer,RAWBUF_SIZE,777)) != 777)
{
if(rcv == 101)
break;
}
// Perform a get request
if(!strcmp(direction,GET))
{
get(client_socket, sa_out, cusername, filename, client_num, server_num, logfile);
}
else if(!strcmp(direction,PUT))
{
put(client_socket, sa_out, cusername, filename, client_num, server_num, logfile);
}
}
else
{
throw "The method you requested does not exist, use get or put";
}
}
catch (const char *str)
{
cerr << str << WSAGetLastError() << endl;
}
//close the client socket and clean up
fclose(logfile);
closesocket(client_socket);
WSACleanup();
}
PUT() CODE
void Client::put(SOCKET s, SOCKADDR_IN sa, char * username, char* filename, int client_num, int server_num, FILE* logfile)
{
char window[FRAME_SIZE * WINDOW_SIZE]; // data retention window
char buffer[FRAME_SIZE]; // send buffer
int filesize;
int size = 0, sent = 0; // Trace variables
char tracebuf[128];
FILE* send_file;
fopen_s(&send_file, filename, "rb");
if(send_file != NULL)
{
// open the file
// Determines the file size
fseek(send_file, 0L, SEEK_END);
filesize = ftell(send_file);
fseek(send_file, 0L, SEEK_SET);
//write filesize to logfile
sprintf(tracebuf, "Filesize %d", filesize);
write_log(logfile, username, tracebuf);
//add file size to buffer
strncpy_s(buffer, "SIZ", 3);
memcpy(buffer + (3 * sizeof(char)), &filesize, sizeof(int));
//if filesize was sent to server successfully
if(send_safe(s,sa,buffer,FRAME_SIZE,101) == 101)
{
cout << "Sent filesize, starting transfer..." << endl;
//reset buffer
memset(buffer, 0, sizeof(buffer));
int count = 0;
int offset = 0;
int frames_outstanding = 0; //for frames not ACKED
int next = 0;
bool resend = false;
int packet_id;
int pid_max = WINDOW_SIZE + 1;
// Start sending the file
while (1)
{
// If the acks mismatch with the current send offset and there are frames not ACKED, this has to be a resend
if(next != offset && frames_outstanding > 0)
resend = true;
// Send as many frames as available for the given window size
while((!feof(send_file) && frames_outstanding < WINDOW_SIZE) || resend)
{
if(next == offset)
resend = false;
if(!resend)
{
if(feof(send_file))
break;
fread(buffer,1,FRAME_SIZE,send_file); // Read the next block of data
memcpy(window + (offset * FRAME_SIZE), buffer, FRAME_SIZE); // Store the data in the local window
//memcpy(window, buffer, FRAME_SIZE); // Store the data in the local window
send_packet(s, sa, buffer, FRAME_SIZE, offset); // Send the packet to peer
offset = (offset + 1) % pid_max; // Update the offset
frames_outstanding++;
}
else
{
// Resend by copying the data from the window
memcpy(buffer, window + (next * FRAME_SIZE), FRAME_SIZE);
send_packet(s, sa, buffer, FRAME_SIZE, next);
//log
sprintf(tracebuf, "Resending packet %d", next);
write_log(logfile, username, tracebuf);
next = (next + 1) % pid_max;
}
}
// Receive ACKs before continuing sending
//while the # of unacked frames are greater than 0
while(frames_outstanding > 0)
{
//if packet id < 0
if((packet_id = recv_packet(s,sa,buffer,FRAME_SIZE,next)) < 0)
{
if(count < filesize)
resend = true;
break;
}
// Receive acknowledgment from the client
if(!strncmp(buffer,"NAK", 3))
{
if(packet_id >= 0)
next = packet_id; // Set the next packet to the packet id
break;
}
else if(!strncmp(buffer,"ALL", 3))
{
frames_outstanding = 0;
break;
}
//log
sprintf(tracebuf, "Sent %d bytes", count);
write_log(logfile, username, tracebuf);
memset(buffer, 0, sizeof(buffer)); // Zero the buffer
next = (next + 1) % pid_max; // Update the next frame tracker
frames_outstanding--; // Another frame has been acked
}
if(feof(send_file) && frames_outstanding == 0)
break; // Break when done reading the file and all frames are acked
}
cout << "File transfer completed" << endl;
fclose(send_file);
}
else
{
fclose(send_file);
return put(s,sa,username,filename, client_num, server_num, logfile);
}
}
}
WRITE_LOG() CODE
void Client::write_log(FILE* logfile, char* username, char* message)
{
fprintf(logfile, "%s > %s\n", username, message);
memset(message, 0, sizeof(message));
}
Not at all sure what you actually intdended to do here:
memset(message, 0, sizeof(message));
but it's likely not doing what you intended. sizeof(message) is either 4 or, more likely, 8 on a modern system. So you are writing 8 zeros to message. Which may not be 8 bytes long in the first place.
Possibly you want:
memset(message, 0, strlen(message));
or:
message[0] = 0;
(Which will do set the string to "empty", but not fill the entire thing with zeros).

C++ socket server responding only to localhost requests, not others on network

Strange. I can make GET requests using the included code on my local machine, and it works like a charm. From the local machine command line, using GET -Ue 192.168.2.106:8129 I get
200 OK
Content-Length: 296
Content-Type: text/html
Client-Date: Sat, 09 Feb 2013 20:26:09 GMT
Client-Response-Num: 1
<html><body><h1>Directory</h1><a href=/.>.</a><br/><a href=/..>..</a><br/><a href=/bldg.jpg>bldg.jpg</a><br/><a href=/hello.txt>hello.txt</a><br/><a href=/world.gif>world.gif</a><br/><a href=/index.html>index.html</a><br/><a href=/testing>testing</a><br/><a href=/favicon.ico>favicon.ico</a><br/>
Wheras from the remote machine I get
200 OK
Content-Length: 328
Content-Type: text/html
Client-Aborted: die
Client-Date: Sat, 09 Feb 2013 20:25:16 GMT
Client-Response-Num: 1
X-Died: read failed: Connection reset by peer at /usr/share/perl5/LWP/Protocol/http.pm line 414.
The second one looks like it wants to work, but the wonky "X-Died" header is odd. I have a sneaking suspicion that my GetLine method is off, but I'm not quite sure. Any idea what could be causing this issue?
Main function:
int main(int argc, char* argv[])
{
// First set up the signal handler
struct sigaction sigold, signew;
signew.sa_handler = handler;
sigemptyset(&signew.sa_mask);
sigaddset(&signew.sa_mask, SIGPIPE);
signew.sa_flags = SA_RESTART;
sigaction(SIGPIPE, &signew, &sigold);
int hSocket,hServerSocket; /* handle to socket */
struct hostent* pHostInfo; /* holds info about a machine */
struct sockaddr_in Address; /* Internet socket address stuct */
int nAddressSize=sizeof(struct sockaddr_in);
char pBuffer[BUFFER_SIZE];
int nHostPort;
q = new myQueue();
// THREAD POOL!
pthread_t thread_id[NUMTHREADS];
int i=0;
for(i=0; i < NUMTHREADS; i++)
{
threadParams param;
param.a = i;
pthread_create(&thread_id[i], 0, &WorkerHandler, NULL);
}
if(argc < 2)
{
printf("\nUsage: server host-port\n");
return 0;
}
else
{
nHostPort = atoi(argv[1]);
}
printf("\nStarting server");
printf("\nMaking socket");
/* make a socket */
hServerSocket=socket(AF_INET,SOCK_STREAM,0);
if(hServerSocket == SOCKET_ERROR)
{
printf("\nCould not make a socket\n");
return 0;
}
/* fill address struct */
Address.sin_addr.s_addr=INADDR_ANY;
Address.sin_port=htons(nHostPort);
Address.sin_family=AF_INET;
printf("\nBinding to port %d",nHostPort);
int optval = 1;
setsockopt(hServerSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
/* bind to a port */
if(bind(hServerSocket,(struct sockaddr*)&Address,sizeof(Address)) == SOCKET_ERROR)
{
printf("\nCould not connect to host\n");
return 0;
}
/* get port number */
getsockname( hServerSocket, (struct sockaddr *) &Address,(socklen_t *)&nAddressSize);
printf("opened socket as fd (%d) on port (%d) for stream i/o\n",hServerSocket, ntohs(Address.sin_port) );
printf("Server\n\
sin_family = %d\n\
sin_addr.s_addr = %d\n\
sin_port = %d\n"
, Address.sin_family
, Address.sin_addr.s_addr
, ntohs(Address.sin_port));
/* establish listen queue */
if(listen(hServerSocket, 1000) == SOCKET_ERROR)
{
printf("\nCould not listen\n");
return 0;
}
while(1)
{
int socket = accept(hServerSocket, (struct sockaddr*)&Address, (socklen_t *)&nAddressSize);
q->enqueue(socket);
}
}
void handler (int status)
{
}
Handle requests on the socket:
int handleRequest(int socket)
{
cout << "handling a request..." << endl;
// Get the URL
char * line = GetLine(socket);
//char * line = "GET /bldg.jpg HTTP/1.1";
char * url;
url = strtok(line, " "); // Splits spaces between words in str
url = strtok(NULL, " "); // Splits spaces between words in str
// build filename
ostringstream fullpathstream;
fullpathstream << dirpath << url;
string fullpath = fullpathstream.str();
//Use the stat function to get the information
struct stat fileAtt;
if (stat(fullpath.c_str(), &fileAtt) != 0) //start will be 0 when it succeeds
{
cout << "File not found:" << fullpath.c_str() << endl;
writeError(socket);
return 0;
}
// Make correct filetypes
if (S_ISREG (fileAtt.st_mode))
{
printf ("%s is a regular file.\n", fullpath.c_str());
char * contentType;
if(strstr(url, ".jpg"))
{
cout << "JPEG" << endl;
contentType = "image/jpg";
}
else if(strstr(url, ".gif"))
{
contentType = "image/gif";
cout << "GIF" << endl;
}
else if(strstr(url, ".html"))
{
contentType = "text/html";
cout << "HTML" << endl;
}
else if(strstr(url, ".txt"))
{
cout << "TXT" << endl;
contentType = "text/plain";
}
else if(strstr(url, ".ico"))
{
cout << "ICO" << endl;
contentType = "image/ico";
}
serveFile(fullpath, socket, fileAtt.st_size, contentType);
}
if (S_ISDIR (fileAtt.st_mode))
{
printf ("%s is a directory.\n", fullpath.c_str());
serveDirectory(socket, url);
}
return 0;
};
GetLine function for getting the first line of the request so I knowt the requested URL:
// Read the line one character at a time, looking for the CR
// You dont want to read too far, or you will mess up the content
char * GetLine(int fds)
{
char tline[MAX_MSG_SZ];
char *line;
int messagesize = 0;
int amtread = 0;
while((amtread = read(fds, tline + messagesize, 1)) < MAX_MSG_SZ)
{
if (amtread > 0)
messagesize += amtread;
else
{
perror("Socket Error is:");
fprintf(stderr, "Read Failed on file descriptor %d messagesize = %d\n", fds, messagesize);
exit(2);
}
//fprintf(stderr,"%d[%c]", messagesize,message[messagesize-1]);
if (tline[messagesize - 1] == '\n')
break;
}
tline[messagesize] = '\0';
chomp(tline);
line = (char *)malloc((strlen(tline) + 1) * sizeof(char));
strcpy(line, tline);
//fprintf(stderr, "GetLine: [%s]\n", line);
return line;
}
I have multithreading happening, and this is where I close my sockets.
void * WorkerHandler(void *arg)
{
threadParams* params = (threadParams*)arg;
while(1)
{
int socket = q->dequeue();
handleRequest(socket);
if(close(socket) == SOCKET_ERROR)
{
printf("\nCould not close socket\n");
return 0;
}
}
}