Related
I'm implementing a server in C++ with non-blocking sockets.
Since I want to send messages between the client & server, I wrote 2 wrappers around send/recv syscalls. Mainly, I want to prepend 4Bytes (message length) to every message, so that the receiver knows how long to execute recv.
Moreover I have a client/server programs that each start a socket and listen on localhost.
Then the client sends a random message, which the server receives.
When I try,however, to send from the server to the client, both programs halt.
I have tested the wrappers many times and they read/deliver data, but whenever I try to receive on a previously sending connection, then comes the problem.
I know that there is a memory leak in the secure_recv but I need it to pass some custom tests, which are not very well written.
The issue lies in the select, which returns a positive number, but then I never go inside the if (FD_ISSET(fd, &readset)) statement.
What am I doing wrong and how can we fix it ? Thanks a lot !
EDIT
My problem was that the sockets were blocking(busy working) at the select function. I updated the code so that there is no select in the secure_* functions. It's a much better way to first check if the socket is available for send/recv on a client/server thread level via select and then calling the secure_* functions. Question is answered for now.
client.cpp
// Client side C/C++ program to demonstrate Socket programming
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include "util.h"
#define PORT 8080
int main(int argc, char const *argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
int numbytes;
size_t size = 0;
std::unique_ptr<char[]> buf = get_rand_data(size);
if ((numbytes = secure_send(sock, buf.get(), size, 0)) == -1)
{
std::cout << std::strerror(errno) << "\n";
exit(1);
}
std::cout << "Client sent : " << numbytes << "\n";
int64_t bytecount = -1;
while (1)
{
std::unique_ptr<char[]> buffer;
if ((bytecount = secure_recv(sock, buffer, 0)) <= 0)
{
if (bytecount == 0)
{
break;
}
}
std::cout << bytecount << "\n";
}
std::cout << "Client received : " << bytecount << "\n";
close(sock);
return 0;
}
server.cpp
// Server side C/C++ program to demonstrate Socket programming
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include "util.h"
#define PORT 8080
int main(int argc, char const *argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address,
sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
// set the socket to non-blocking mode
fcntl(new_socket, F_SETFL, O_NONBLOCK);
int64_t bytecount = -1;
while (1) {
std::unique_ptr<char[]> buffer;
if ((bytecount = secure_recv(new_socket, buffer, 0)) <= 0) {
if (bytecount == 0) {
break;
}
}
std::cout << bytecount << "\n";
}
int numbytes;
size_t size = 0;
std::unique_ptr<char[]> buf = get_rand_data(size);
if ((numbytes = secure_send(new_socket, buf.get(), size, 0)) == -1)
{
std::cout << std::strerror(errno) << "\n";
exit(1);
}
std::cout << "Client sent : " << numbytes << "\n";
close(new_socket);
return 0;
}
util.h
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <signal.h>
#include <cstring>
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <condition_variable>
#include <algorithm>
#include <memory>
#include <poll.h>
#include <iomanip>
/**
* It takes as arguments one char[] array of 4 or bigger size and an integer.
* It converts the integer into a byte array.
*/
void convertIntToByteArray(char *dst, int sz)
{
auto tmp = dst;
tmp[0] = (sz >> 24) & 0xFF;
tmp[1] = (sz >> 16) & 0xFF;
tmp[2] = (sz >> 8) & 0xFF;
tmp[3] = sz & 0xFF;
}
/**
* It takes as an argument a ptr to an array of size 4 or bigger and
* converts the char array into an integer.
*/
int convertByteArrayToInt(char *b)
{
return (b[0] << 24) + ((b[1] & 0xFF) << 16) + ((b[2] & 0xFF) << 8) + (b[3] & 0xFF);
}
/**
* It constructs the message to be sent.
* It takes as arguments a destination char ptr, the payload (data to be sent)
* and the payload size.
* It returns the expected message format at dst ptr;
*
* |<---msg size (4 bytes)--->|<---payload (msg size bytes)--->|
*
*
*/
void construct_message(char *dst, char *payload, size_t payload_size)
{
convertIntToByteArray(dst, payload_size);
memcpy(dst + 4, payload, payload_size);
}
/**
* It returns the actual size of msg.
* Not that msg might not contain all payload data.
* The function expects at least that the msg contains the first 4 bytes that
* indicate the actual size of the payload.
*/
int get_payload_size(char *msg, size_t bytes)
{
// TODO:
return convertByteArrayToInt(msg);
}
/**
* Sends to the connection defined by the fd, a message with a payload (data) of size len bytes.
* The fd should be non-blocking socket.
*/
/**
* Receives a message from the fd (non-blocking) and stores it in buf.
*/
int secure_recv(int fd, std::unique_ptr<char[]> &buf)
{
// TODO:
int valread = 0;
int len = 0;
int _len = 4;
bool once_received = false;
std::vector<char> ptr(4);
while (_len > 0)
{
int _valread = recv(fd, ptr.data() + valread, _len, MSG_DONTWAIT);
if (_valread == 0)
{
break;
}
if (_valread > 0)
{
_len -= _valread;
valread += _valread;
}
if (!once_received && valread == 4)
{
once_received = true;
len = convertByteArrayToInt(ptr.data());
_len = len;
ptr = std::vector<char>(len);
valread = 0;
}
}
buf = std::make_unique<char[]>(len);
memcpy(buf.get(), ptr.data(), len);
return len;
}
/**
* Sends to the connection defined by the fd, a message with a payload (data) of size len bytes.
* The fd should be non-blocking socket.
*/
int secure_send(int fd, char *data, size_t len)
{
// TODO:
char ptr[len + 4];
int valsent = 0;
int _len = 4;
bool once_sent = false;
construct_message(ptr, data, len);
while (_len > 0)
{
int _valsent = send(fd, ptr + valsent, _len, MSG_DONTWAIT);
if (_valsent == 0)
{
break;
}
if (_valsent > 0)
{
_len -= _valsent;
valsent += _valsent;
}
if (!once_sent && valsent == 4)
{
once_sent = true;
_len = len;
}
}
return len;
}
Compilation via
g++ -O3 -std=c++17 -Wall -g -I../ client.cpp -o client -lpthread
Let's start with the write loop:
while (1)
{
// std::cerr << "first iteration send\n";
FD_ZERO(&writeset);
FD_SET(fd, &writeset);
if (select(fd + 1, NULL, &writeset, NULL, NULL) > 0)
{
if (FD_ISSET(fd, &writeset))
{
valsent = send(fd, ptr + valsent, _len, 0);
Oops. This loses valsent, which tracks how many bytes you've sent so far. So on your third loop, ptr + valsent will only add the number of bytes received the second time. You need to track the total number of bytes sent so far somewhere.
if (valsent <= 0)
{
break;
}
_len -= valsent;
And what if _len becomes zero? You'll still call select and even send. You probably want that while (1) to be while (_len > 0).
}
}
}
return len;
Now, onto the read loop:
if (select(fd + 1, &readset, NULL, NULL, NULL) > 0)
{
if (FD_ISSET(fd, &readset))
{
if (first_iteration)
{
recv(fd, ptr, 4, 0);
You ignore the return value of recv here. What if it's not 4?
len = convertByteArrayToInt(ptr);
buf = std::make_unique<char[]>(len);
_len = len;
first_iteration = false;
}
valread = recv(fd, buf.get() + valread, _len, 0);
if (valread <= 0)
{
break;
}
_len -= valread;
You don't leave the loop if _len is zero. You'll call select again, waiting for data that may never come.
}
}
I got an error:
dereferencing pointer to incomplete type 'struct ip'
138| u_int8_t icmp_Type = icmp_package->icmp_type;
I've made some research, found some similar topics on this, but nothing helped. The problem probably is with icmp.
The program works like traceroute in a Linux terminal.
None of these seem to work to fix it:
adding -D_GNU_SOURCE to gcc command
adding __USE_BSD
Does anyone know how to solve it?
Compiling on Linux with gcc -std=c17
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
int receive_from(int sockfd, char recipient[20], int PID, int TTL, char response[20]);
void print_as_bytes (unsigned char* buff, ssize_t length)
{
for (ssize_t i = 0; i < length; i++, buff++)
printf ("%.2x ", *buff);
}
void print_row(int RCV_NUM, int avg, int TTL, char responses[3][20])
{
if(TTL < 10)
printf(" ");
printf("%d", TTL);
if(RCV_NUM == 0)
{
printf("*\n");
} else {
printf(" %s", responses[0]);
if(strcmp(responses[0], responses[1]) != 0)
printf(" %s", responses[1]);
if(strcmp(responses[0], responses[2]) != 0 && strcmp(responses[1], responses[2]) != 0)
printf(" %s", responses[2]);
if(RCV_NUM < 3)
printf(" ???\n");
else
printf(" %d ms", avg);
}
}
int receive(int sockfd, char recipient[20], int PID, int TTL)
{
int DEST_REACHED = 0;
char responses[3][20] = {"", "", ""};
struct timeval time;
gettimeofday(&time, NULL);
long long start = ((long long)time.tv_sec * 1000) + (time.tv_usec / 1000);
fd_set descriptors;
FD_ZERO(&descriptors);
FD_SET(sockfd, &descriptors);
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
int time_passed = 0;
int which = 0;
while(which < 3)
{
int ready = select (sockfd+1, &descriptors, NULL, NULL, &tv);
if(ready < 0)
{
fprintf(stderr, "traceroute: select error: %s\n", strerror(errno));
which++;
}
if(ready > 0)
{
gettimeofday(&time, NULL);
long long timeNow = ((long long)time.tv_sec * 1000) + (time.tv_usec / 1000);
time_passed += timeNow - start;
int result = receive_from(sockfd, recipient, PID, TTL, responses[which]);
if(result == -1)
{
fprintf(stderr, "traceroute: Package missed\n");
which++;
continue;
}
if(result == 1)
{
DEST_REACHED = 1;
}
which++;
if(which == 3)
{ break; }
}
if(ready == 0)
{
which++;
}
}
int avg;
int RCV_NUM = 3;
if(which < 3)
{
RCV_NUM = which;
} else {
avg = time_passed / 3;
}
print_row(RCV_NUM, avg, TTL, responses);
return DEST_REACHED;
}
int receive_from(int sockfd, char recipient[20], int PID, int TTL, char response[20])
{
struct sockaddr_in sender;
socklen_t sender_len = sizeof(sender);
u_int8_t buffer[IP_MAXPACKET];
ssize_t packet_len = recvfrom (sockfd, buffer, IP_MAXPACKET, 0, (struct sockaddr*)&sender, &sender_len);
if (packet_len < 0) {
fprintf(stderr, "recvfrom error: %s\n", strerror(errno));
return EXIT_FAILURE;
}
char sender_ip_str[20];
inet_ntop(AF_INET, &(sender.sin_addr), sender_ip_str, sizeof(sender_ip_str));
printf ("Received IP packet with ICMP content from: %s\n", sender_ip_str);
struct ip* ip_header = (struct ip*) buffer;
ssize_t ip_header_len = 4 * ip_header->ip_hl;
struct icmp* icmp_package = (struct icmp*)((uint8_t *)ip_header + ip_header_len);
u_int8_t icmp_Type = icmp_package->icmp_type;
u_int8_t icmp_Code = icmp_package->icmp_code;
//We reached the destination point
if(icmp_Type == 0 && icmp_Code == 0)
{
if(icmp_package->icmp_hun.ih_idseq.icd_id == (u_int16_t) PID && icmp_package->icmp_hun.ih_idseq.icd_id == (u_int16_t) TTL)
{
inet_ntop(AF_INET, &(sender.sin_addr), response, 20);
return 1;
}
}
//Time Exceeded - we are not yet in the destination point
if(icmp_Type == 11 && icmp_Code == 0)
{
struct ip* ip_header_md = (struct ip *)((uint8_t *)icmp_package + 8);
struct icmp* icmp_package_md = (struct icmp *)((uint8_t *)ip_header_md + (*ip_header_md).ip_hl * 4);
if(icmp_package_md->icmp_hun.ih_idseq.icd_id == (u_int16_t) PID && icmp_package_md->icmp_hun.ih_idseq.icd_id == (u_int16_t) TTL)
{
inet_ntop(AF_INET, &(sender.sin_addr), response, 20);
return 0;
}
}
//Błąd
return -1;
}
I'm attempting to implement a GoBackN protocol and when the server drops a packet, my alarm waits 2 seconds before sending all previously sent packets.
The alarm works and waits 2 seconds, however after the first timeout, the state machine I'm using gets stuck in a loop and continues to timeout. I think it might be because errno is not getting reset, but I'm not sure.
#define TIMEOUT_SECS 2
#define MAXTRIES 10
int base = 0;
int windowSize = 7;
int sendFlag = 1;
int tries = 0;
int numPackets = 0;
packet *packetArray[30];
void addPacket(packet *p)
{
for (int i = 0; i < 30; i++)
{
if (packetArray[i])
{
continue;
}
else
{
packetArray[i] = p;
numPackets++;
break;
}
}
}
void
CatchAlarm(int ignored) /* Handler for SIGALRM */
{
tries += 1;
errno = 0;
}
void
DieWithError()
{
printf("error");
exit (1);
}
int
max(int a, int b)
{
if (b > a)
return b;
return a;
}
int
min(int a, int b)
{
if(b>a)
return a;
return b;
}
typedef enum
{
wait,
sendData,
timeout,
receiveData
} e_state;
int main(int argumentCount, char *argumentVariables[])
{
//Grabbing all input information.
struct hostent *emulatorName;
emulatorName = gethostbyname(argumentVariables[1]);
int receiveFromEmulator = atoi(argumentVariables[3]);
int sendToEmulator = atoi(argumentVariables[2]);
//Setting up UDP socket for receiving from emulator.
int receiveSocket = 0;
receiveSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//UDP socket configuration.
struct sockaddr_in receiveSocketStruct;
bzero((char *) &receiveSocketStruct, sizeof(receiveSocketStruct));
receiveSocketStruct.sin_family = AF_INET;
receiveSocketStruct.sin_port = htons(receiveFromEmulator);
receiveSocketStruct.sin_addr.s_addr = INADDR_ANY;
socklen_t receiveSocketLen = sizeof(receiveSocketStruct);
//Binding UDP socket so client can locate emulator.
bind(receiveSocket, (struct sockaddr *)&receiveSocketStruct, sizeof(receiveSocketStruct));
//Setting up UDP socket for sending to emulator.
int sendSocket = 0;
sendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
//UDP socket configuration.
struct sockaddr_in sendSocketStruct;
bzero((char *) &sendSocketStruct, sizeof(sendSocketStruct));
sendSocketStruct.sin_family = AF_INET;
sendSocketStruct.sin_port = htons(sendToEmulator);
sendSocketStruct.sin_addr.s_addr = INADDR_ANY;
socklen_t sendSocketLen = sizeof(sendSocketStruct);
char buffer[1024];
std::ifstream infile (argumentVariables[4], std::ifstream::binary);
infile.seekg (0, infile.end);
int lengthOfFile = infile.tellg();
infile.seekg (0, infile.beg);
int totalPackets = 0;
int nextSeqNum = 0;
while(1)
{
if (lengthOfFile > 30)
{
bzero(buffer, 1024);
char * data = new char[1024];
infile.read(buffer, 30);
strncpy(data, buffer, 1024);
lengthOfFile -= 30;
if (nextSeqNum > 7)
{
nextSeqNum = 0;
}
addPacket(new packet(1, nextSeqNum, strlen(data), data));
totalPackets++;
nextSeqNum++;
}
else
{
bzero(buffer, 1024);
char * data = new char[1024];
infile.read(buffer, 30);
strncpy(data, buffer, 1024);
if (nextSeqNum > 7)
{
nextSeqNum = 0;
}
addPacket(new packet(1, nextSeqNum, strlen(data), data));
totalPackets++;
nextSeqNum++;
addPacket(new packet(3, nextSeqNum, 0, NULL));
totalPackets++;
break;
}
}
infile.close();
nextSeqNum = 0;
int packetsReceived;
int sentPackets;
int receive = 0;
char receivePayload[1024];
char sendPayload[1024];
struct sigaction myAction; /* For setting signal handler */
myAction.sa_handler = CatchAlarm;
if (sigfillset (&myAction.sa_mask) < 0) /* block everything in handler */
DieWithError ();
myAction.sa_flags = 0;
if (sigaction (SIGALRM, &myAction, 0) < 0)
DieWithError ();
e_state currentState = wait;
e_state previousState = wait;
while(1)
{
if (currentState == wait)
{
if (sendFlag == 1)
{
previousState = currentState;
currentState = sendData;
}
else
{
previousState = currentState;
currentState = receiveData;
}
}
else if (currentState == sendData)
{
if ((nextSeqNum < base + windowSize) && (nextSeqNum < totalPackets - 1))
{
//send packet with seqnum.
int sendPacket = 0;
bzero(sendPayload, 1024);
packet * sendpckt = packetArray[nextSeqNum];
sendpckt->serialize(sendPayload);
sendpckt->printContents();
sendPacket = sendto(sendSocket, sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen);
if (base == nextSeqNum)
{
alarm(0);
alarm(TIMEOUT_SECS);
}
nextSeqNum++;
}
else
{
sendFlag = 0;
previousState = currentState;
currentState = wait;
}
}
else if (currentState == timeout)
{
alarm(0);
alarm(TIMEOUT_SECS);
for(int counter = base; counter < nextSeqNum; counter++)
{
int sendPacket = 0;
bzero(sendPayload, 1024);
packet * sendpckt = packetArray[counter];
sendpckt->serialize(sendPayload);
sendpckt->printContents();
sendPacket = sendto(sendSocket, sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen);
}
sendFlag = 0;
previousState = currentState;
currentState = wait;
}
else if (currentState == receiveData)
{
bzero(receivePayload, 1024);
receive = (recvfrom(receiveSocket, receivePayload, sizeof(receivePayload), 0, (struct sockaddr *)&receiveSocketStruct, &receiveSocketLen));
if (errno == EINTR)
{
printf("timeout");
if (tries > MAXTRIES)
{
alarm(0);
break;
printf("recvfrom() failed.");
}
previousState = currentState;
currentState = timeout;
}
else
{
char buffer[1024];
bzero(buffer, 1024);
int receivePacketType;
int receivePacketSeqNum;
packet recvpckt(0, 0, 0, (char*)buffer);
recvpckt.deserialize((char*)receivePayload);
receivePacketSeqNum = recvpckt.getSeqNum();
receivePacketType = recvpckt.getType();
recvpckt.printContents();
if (receivePacketType == 2)
{
break;
}
base = receivePacketSeqNum + 1;
printf("%d\n", base);
if (base == nextSeqNum)
{
alarm(0);
}
else
{
alarm(0);
alarm(TIMEOUT_SECS);
}
if (nextSeqNum == totalPackets - 1)
{
nextSeqNum++;
int sendPacket = 0;
bzero(sendPayload, 1024);
packet * sendpckt = packetArray[nextSeqNum - 1];
sendpckt->serialize(sendPayload);
sendpckt->printContents();
sendPacket = sendto(sendSocket, sendPayload, sizeof(sendPayload), 0, (struct sockaddr *)&sendSocketStruct, sendSocketLen);
}
if (base <= totalPackets)
{
sendFlag = 1;
previousState = currentState;
currentState = wait;
}
else
{
continue;
}
}
}
else
{
break;
}
}
//Close shop.
close(receiveSocket);
close(sendSocket);
return 0;
}
The location where I suspect the loop to start is in the receiveData state.
Fixed it:
else if (currentState == receiveData)
{
receive = 0;
bzero(receivePayload, 1024);
receive = (recvfrom(receiveSocket, receivePayload, sizeof(receivePayload), 0, (struct sockaddr *)&receiveSocketStruct, &receiveSocketLen));
if (receive < 0)
{
printf("timeout");
if (tries > MAXTRIES)
{
alarm(0);
break;
printf("recvfrom() failed.");
}
previousState = currentState;
currentState = timeout;
}
Why can't this program connect to the socket?
I know that WSAStartup fails, but I can't figure out how to use it.
#include "StdAfx.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <string.h>
#include <errno.h>
#pragma comment(lib, "ws2_32.lib")
int sockd;
#define SocketErrno (WSAGetLastError())
#define bcopy(src,dest,len) memmove(dest,src,len)
typedef signed char int8;
typedef signed long int32;
inline int WriteInt8(char *buf, int pos, int8 value) { buf[pos] = (int8)(value); return 1; }
inline int WriteInt32(char *buf, int pos, int32 value) { buf[pos] = (int8)(value >> 24); buf[pos+1] = (int8)(value >> 16); buf[pos+2] = (int8)(value >> 8); buf[pos+3] = (int8)(value); return 4; }
inline int WriteASCII(char *start_buf, int pos, const char *start, int length) { int startPos = 0; char *buf = &start_buf[pos]; for (int i = 0; i < length; ++i) { buf[i] = start[startPos]; if (start[startPos]) ++startPos; } return length; }
size_t writen(int fd, const char *vptr, size_t n)
{
size_t nleft;
size_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0)
{
if ( (nwritten = writen(fd, ptr, nleft)) <= 0)
{
if (errno == EINTR)
nwritten = 0;
else
return(-1);
}
nleft -= nwritten;
ptr += nwritten;
}
return(n);
}
bool login(char *Username, char *Password, int characterID)
{
char buffer[8192];
int pos = 0;
pos += WriteInt8(buffer, pos, 0x91u);
pos += WriteInt8(buffer, pos, 58);
pos += WriteInt8(buffer, pos, 0xFFu);
pos += WriteInt8(buffer, pos, 55);
pos += WriteInt8(buffer, pos, 40);
pos += WriteASCII(buffer, pos, Username, 30);
pos += WriteASCII(buffer, pos, Password, 30);
if( writen(sockd, buffer, 65) < 65)
return false;
WriteInt8(buffer, 0, 0x5D);
WriteInt32(buffer, 65, characterID);
if( writen(sockd, buffer, 73) < 73)
return false;
return true;
}
bool connect(char *ServerAddress, int ServerPort)
{
struct sockaddr_in servaddr;
if ( (sockd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
return false;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(ServerPort);
if ( inet_pton(AF_INET, ServerAddress, &servaddr.sin_addr) <= 0 )
return false;
if ( connect(sockd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 )
return false;
char seed[4] = { 0x3au, 0xFFu, 55, 40 };
if( writen(sockd, seed, 4) < 0)
return false;
return true;
}
int main(int argc, char * argv[])
{
bool wArgs = true;
if (argc == 1)
{
wArgs = false;
}
else if (argc != 4)
{
printf("USAGE: %s User Password CharacterNumber\n", argv[0]);
return 51;
}
printf("stuff");
char *user = new char[20];
char *pass = new char[20];
int pg;
if (wArgs)
{
user = argv[1];
pass = argv[2];
pg = atoi(argv[3]);
}
else
{
printf("*****************************************\n\nUser: ");
scanf("%s", user);
printf("Pass: ");
scanf("%s", pass);
printf("Character Number: ");
scanf("%d", &pg);
printf("\n*****************************************\n");
}
if (!connect("ip hidden,port hidden))
{
printf("Error at socket(): %ld\n", WSAGetLastError());
return 1;
}
if (!login(user, pass, pg))
return 103;
char version[12] = { 0xBDu, 0x00u, 0x0Cu, 0x36u, 0x2Eu, 0x30u, 0x2Eu, 0x31u, 0x2Eu, 0x31u, 0x30u, 0x00 };
if ( writen(sockd, version, 12) < 0 )
return 105;
for(;;)
{
//12 00 09 24 32 31 20 30 00 ...l.....$21 0.
char refresh[9] = { 0x12, 0x00, 0x09, 0x24, 0x32, 0x31, 0x20, 0x30, 0x00 };
if( writen(sockd, refresh, 9) < 0)
return 104;
Sleep(40);
}
return 1;
}
10093 is WSANOTINITIALISED, which means WSAStartup() has not been called yet. The documentation for WSAStartup is pretty clear, if a bit verbose, and even includes a fairly complete example.
You must call WSAStartup before using any other Winsock functions:
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
You may also want to checkout out the WinSock FAQ when learning to do WinSock programming.
sending and recieving file from tcp socket. Sending the file works however trying to save the file does not work.
#include <cassert>
#include <arpa/inet.h>
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <fstream>
#include <time.h>
#include <strings.h>
#include <sstream>
#include <vector>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/sendfile.h>
#include <fcntl.h>
using namespace std;
using std::endl;
int newscount = 0;
int doccount = 0;
int photocount = 0;
int johns = 0;
vector<string> newsvector;
vector<string> photosvector;
vector<string> docsvector;
void serverlogs(const char*msg) /* writing to log file */
{
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime(&rawtime);
ofstream file;
file.open("serverlog.txt",ios::app);
if (file.is_open())
{file<<msg;
file<<" # ";
file<<asctime(timeinfo);
file<<"\n";
file.close();
return;
}
else
cout<<"Error Creating log file";
return;
}
void clientlogs(const char*msg) /* writing to log file */
{
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime(&rawtime);
ofstream file;
file.open("clientlog.txt",ios::app);
if (file.is_open())
{file<<msg;
file<<" # ";
file<<asctime(timeinfo);
file<<"\n";
file.close();
return;
}
else
cout<<"Error Creating log file";
return;
}
void error(const char*msg) /* If there is an error exit the program with err# 1 */
{
perror(msg);
exit(1);
}
void publishdocsvector(const char*msg)
{
docsvector.push_back(msg);
ofstream file;
file.open("docfiles.txt",ios::app);
if (file.is_open())
{
for(int j = 0; j < docsvector.size() ;j++)
{file<<docsvector[j];}
file.close();
}
else
cout<<"Error creating news archive";
return;
}
void publishphotosvector(const char*msg)
{
photosvector.push_back(msg);
ofstream file;
file.open("photofiles.txt",ios::app);
if (file.is_open())
{
for(int j = 0; j < photosvector.size() ;j++)
{file<<photosvector[j];}
file.close();
}
else
cout<<"Error creating news archive";
return;
}
void publishnewsvector(const char*msg)
{
newsvector.push_back(msg);
ofstream file;
file.open("newsfiles.txt",ios::app);
if (file.is_open())
{
for(int j = 0; j < newsvector.size() ;j++)
{file<<newsvector[j];}
file.close();
}
else
cout<<"Error creating news archive";
return;
}
void sendfile(const char*msg)
{
// to be implemented later//
}
int main (int argc, char*argv[]) /*Main Program accepting a port number and something else for arguments */
{
int sockfd, newsockfd, portno, clilen, n,test;
string publish="publish";
string search= "search";
string get="get";
string newsstring = "news";
string docstring = "doc";
string photostring = "photo";
string wrap = "exit";
char buffer[256];
char seats [50];
serverlogs("Server Running");
struct sockaddr_in serv_addr, cli_addr; /* Defines the server address and client address and types of structures with the same format as socket address */
if (argc < 2)
{
fprintf(stderr,"Please provide a port number next time plz, goodbye!");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0); /* If Sock_Dgram then then it will open a udp socket */
if (sockfd < 0)
error("Error opening socket");
bzero((char *)&serv_addr, sizeof(serv_addr)); /* sets the server address to zero usings its reference */
portno = atoi(argv[1]); /*2nd argument vector is the port number and converted into an integer, the first [0] is the running program */
serv_addr.sin_family = AF_INET; /* The structure sockaddr_in has four fields, this is first one and should always be this */
serv_addr.sin_port = htons(portno); /* convert port number into network byte order */
serv_addr.sin_addr.s_addr = INADDR_ANY; /*3rd Field uses Ip address of host machine */
if (bind(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr))<0) /*bind socket to sockfd and address of server ,and needs size of address need struct of sockaddr, see bind man for details*/
error("Couldn't bind socket to address");
listen(sockfd,5);
clilen = sizeof(cli_addr);
serverlogs("going into server loop");
int pid = fork();
if (pid < 0)
serverlogs("error on initial separtion of server and client");
if (pid==0)
{
// server loop later on this will be the child process and client will be main
while (1)
{ /* Server loop loop*/
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, (socklen_t*)&clilen);
if (newsockfd < 0)
/* error("Corrupt log"); */
serverlogs("Connection not accepted");
else (newsockfd > 0);
int ppID = fork();
if (ppID < 0)
serverlogs("A new server process failed to be created");
if (ppID == 0)
{
int uid;
uid = johns;
printf("A new client connected with identity: %d\n", getpid());
close(sockfd);
serverlogs("A john Connected to the server");
printf("my unique id: %d\n", uid);
serverlogs(seats);
bzero(buffer,256);
//n = write(newsockfd,"Each client is a 'john' \n",26);
/* This loop read from socket and writes to other persons sockets */
while(1)
{
bzero(buffer,256);
n = read(newsockfd,buffer,256);
if (n < 0)
printf ("error reading from socket here is the message: %s",buffer);
if (publish[0] == buffer[0])
{
n = write(newsockfd,"What category are you publishing in?(news,photos,documents) \n",62);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
if(buffer[0]==newsstring[0])
{
n = write(newsockfd,"Type the name of the file to publish and wait 10 seconds \n",59);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
publishnewsvector(buffer);
serverlogs(seats);
serverlogs("client is trying to publish a news file:");
serverlogs(buffer);
/*start recieving a file*/
std::ofstream file;
file.open(buffer, std::ios::out | std::ios::binary);
assert(file.is_open());
while (1) {
std::cout << "..";
bzero(buffer,256);
n = read(newsockfd, buffer, sizeof(buffer));
assert(n != -1);
if (n == 0)
break;
file.write(buffer, n);
i++;
}
file.close();
serverlogs("File Transfered successfully");
}
if(buffer[0]==docstring[0])
{
n = write(newsockfd,"Type the name of the file to publish \n",39);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
publishdocsvector(buffer);
serverlogs(seats);
serverlogs("client is tyring to publish a document:" );
serverlogs(buffer);
/*start recieving a file*/
std::ofstream file;
file.open(buffer, std::ios::out | std::ios::binary);
assert(file.is_open());
while (1) {
std::cout << ".";
bzero(buffer,256);
n = read(newsockfd, buffer, sizeof(buffer));
assert(n != -1);
if (n == 0)
break;
file.write(buffer, n);
}
file.close();
serverlogs("File Transfered successfully");
}
if(buffer[0]==photostring[0])
{
n = write(newsockfd,"Type the name of the file to publish \n",39);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
publishphotosvector(buffer);
serverlogs(seats);
serverlogs("client is trying to publish photo file:" );
serverlogs(buffer);
/*start recieving a file*/
std::ofstream file;
file.open(buffer, std::ios::out | std::ios::binary);
assert(file.is_open());
while (1) {
std::cout << ".";
bzero(buffer,256);
n = read(newsockfd, buffer, sizeof(buffer));
assert(n != -1);
if (n == 0)
break;
file.write(buffer, n);
}
file.close();
serverlogs("File Transfered successfully");
}
}
if (get[0] ==buffer[0])
{
n = write(newsockfd,"\n What file do you want to get? \n",35);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
serverlogs(seats);
serverlogs("client wants file:");
serverlogs(buffer);
//** start sending the file**//
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen(buffer,"r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
n = write(newsockfd,bufferfile,256);
fclose(searchfile);
serverlogs("Sent the file to the client");
serverlogs(seats);
}
if (search[0] == buffer[0])
{
bzero(buffer,256);
n = write(newsockfd,"What category are you searching? \n",35);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
serverlogs(seats);
serverlogs("client searching for");
serverlogs(buffer);
if(buffer[0]==newsstring[0])
{
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen("newsfiles.txt","r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
n = write(newsockfd,bufferfile,256);
fclose(searchfile);
}
if(buffer[0]==docstring[0])
{
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen("docfiles.txt","r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
n = write(newsockfd,bufferfile,256);
fclose(searchfile);
}
if(buffer[0]==photostring[0])
{
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen("photofiles.txt","r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
n = write(newsockfd,bufferfile,256);
fclose(searchfile);
}
}
if(buffer[0]==wrap[0])
{
close(sockfd);
close(newsockfd);
johns = johns - 1;
serverlogs("A john left");
return 0;
}
n = write(newsockfd,"\n Waiting for a command I can understand:(publish,search,get,exit)",66);
} /* while loop to listen to commands from client bracket */
}/*what to do when client connected*/
} /*Creating child/zombies */
} /* division between client and server*/
else
{
while (1)
{int ssockfd, pportno, p,peer;
struct sockaddr_in peer_addr;
struct hostent *peerserver;
char bbuffer[256];
printf ("%s \n", "Welcome to the Social");
printf ("%s \n", "Please type the port number of the server \n");
cin>>pportno;
ssockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket Please try again");
printf ("%s \n", "Please type in the hostname of client ie sunlab1.njit.edu \n");
char peers[256];
cin >> peers;
peerserver = gethostbyname(peers);
if (peerserver == NULL)
{
fprintf(stderr,"could not connect to ip address");
peerserver = gethostbyname((const char*)peer);
if (peerserver == NULL)
fprintf(stderr,"still null");
exit(0);
}
bzero((char *) &peer_addr, sizeof(peer_addr));
peer_addr.sin_family = AF_INET;
bcopy((char *)peerserver->h_addr,(char *)&peer_addr.sin_addr.s_addr,peerserver->h_length);
peer_addr.sin_port = htons(pportno);
if (connect(ssockfd,(struct sockaddr *)&peer_addr,sizeof(peer_addr)) < 0)
error("ERROR connecting");
clientlogs("Connected to peer");
clientlogs((const char*)&peer);
printf("Please enter a command, publish,search or get: ");
while (1)
{
bzero(bbuffer,256);
fgets(bbuffer,255,stdin);
char apub[] = "publish";
char asearch[] = "search";
char aget[]="get";
if (bbuffer[0]==apub[0] && bbuffer[1]==apub[1])
{
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); //What category are you publishing in//
bzero(bbuffer,256);
fgets(bbuffer,255,stdin);
p = write(ssockfd,bbuffer,strlen(bbuffer));
clientlogs("Client publishing");
clientlogs(bbuffer);
if (p < 0)
error("ERROR writing to socket");
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); //Type the name of the file//
fgets(bbuffer,255,stdin);
p = write(ssockfd,bbuffer,strlen(bbuffer));
clientlogs(bbuffer);
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen(bbuffer,"r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
p = write(ssockfd,bufferfile,256);
fclose(searchfile);
}
if(bbuffer[0]==aget[0] && bbuffer[1]==aget[1])
{
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); //What file do you want to get? //
bzero(bbuffer,256);
fgets(bbuffer,255,stdin);
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
clientlogs("client wants file:");
clientlogs(bbuffer);
/*start recieving a file*/
std::ofstream file;
file.open(bbuffer, std::ios::out | std::ios::binary);
assert(file.is_open());
char buffer[255];
while (1) {
std::cout << ".";
bzero(bbuffer,256);
p = read(ssockfd, bbuffer, sizeof(bbuffer));
assert(p != -1);
if (p == 0)
break;
file.write(bbuffer, p);
}
file.close();
serverlogs("File Transfered successfully");
}
if (bbuffer[0]==asearch[0] && bbuffer[1]==asearch[1])
{
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); // what category? //
fgets(bbuffer,255,stdin);
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
clientlogs("Client searching for file");
clientlogs(bbuffer);
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); //The vector array of the files //
}
if (bbuffer[0]==wrap[0] && bbuffer[1]==wrap[1])
{ p = write(ssockfd,bbuffer,strlen(bbuffer));
exit(0); }
}//end of client loop asking to enter a command
}
}
return 0;
}
The problem I see is file << bbuffer. The ofstream's << operator writes until the first NULL byte. Don't forget your buffer is a string (or better, a char *). So, if bbuffer doesn't contain a NULL byte, your program is likely to crash with a SIGSEGV.
You should use file.write(bbuffer, p) instead of file << bbuffer. Also, there's no need to cleanup your buffer using bzero or memset.
And since you didn't provide a compilable source, I wrote the following (supposing Linux/Unix):
#include <cassert>
#include <iostream>
#include <fstream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in sa_dst;
memset(&sa_dst, 0, sizeof(struct sockaddr_in));
sa_dst.sin_family = AF_INET;
sa_dst.sin_port = htons(1234);
sa_dst.sin_addr.s_addr = inet_addr("127.0.0.1");
int ret = connect(fd, (struct sockaddr *)&sa_dst, sizeof(struct sockaddr));
assert(ret != -1);
std::ofstream file;
file.open("received.bin", std::ios::out | std::ios::binary);
assert(file.is_open());
char buffer[255];
while (1) {
std::cout << "..";
ssize_t p = read(fd, buffer, sizeof(buffer));
assert(p != -1);
if (p == 0)
break;
file.write(buffer, p);
}
file.close();
}
You can test it using netcat on your terminal:
$ nc -l 1234 < some_binary_file &
$ ./program
$ cmp some_binary_file received.bin