Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am using shared memory to pass values between processes. It's working the first time, but when I try changing it again, the value is not getting reflected in other processes. First process A changes the value and signal B. It uses it and passes back the control to A. Then A again changes the value, but this new value is not getting reflected in process B.
// FILE 1
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/time.h>
#include<iostream>
#include<netinet/in.h>
#include<sys/select.h>
#include<sys/shm.h>
#include<signal.h>
using namespace std;
struct shm
{
int aid;
int sid;
int bid;
int cid;
int portno;
int pno;
//int ports[4];
}*val;
int ports[4];
int sfds[4];
int count = 4;
void func1(int a)
{
fd_set rfds;
while (1)
{
FD_ZERO(&rfds);
struct timeval timer;
timer.tv_sec = 0;
timer.tv_usec = 10;
for (int i = 0; i < count; i++)
{
FD_SET(sfds[i], &rfds);
}
if (select(sfds[count - 1] + 1, &rfds, NULL, NULL, &timer))
{
for (int i = 0; i < count; i++)
{
if (FD_ISSET(sfds[i], &rfds))
{
val->pno = i;
val->portno = ports[i];
cout << "port number:" << val->portno << endl;
close(sfds[i]);
// Remove the corresponding sfd
for (int j = i; j < count - 1; j++)
{
sfds[j] = sfds[j + 1];
ports[j] = ports[j + 1];
}
count--;
kill(val->aid, SIGUSR2);
if (count > 0)
signal(SIGUSR1, &func1);
else
exit(1);
return;
}
}
}
}
}
void func2(int b)
{
struct sockaddr_in cliaddr;
socklen_t clilen;
int lc = 0;
for (int i = 0; i < 1; i++)
{
int nsfd = accept(sfds[val->pno], (struct sockaddr*) &cliaddr, &clilen);
if (nsfd < 0)
{
perror("Error");
exit(1);
}
cout << "Connection accepted";
send(nsfd, "OkaA", 5, 0);
close(nsfd);
}
if (close(sfds[val->pno]) < 0)
{
perror("Error closing");
exit(1);
}
cout << "Closed" << endl;
// Remove the corresponding sfd
for (int i = val->pno; i < count - 1; i++)
{
sfds[i] = sfds[i + 1];
ports[i] = ports[i + 1];
}
count--;
cout << " val->portnumber " << val->portno << endl;
kill(val->bid, SIGUSR1);
if (count > 0)
signal(SIGUSR2, &func2);
else
exit(1);
return;
}
int main()
{
int shmid = shmget(123456, sizeof(struct shm), IPC_CREAT | 0666);
if (shmid < 0)
{
perror("Error");
}
val = (struct shm*) shmat(shmid, NULL, 0);
//cout<<"yo2";
signal(SIGUSR1, &func1);
signal(SIGUSR2, &func2);
for (int i = 0; i < 4; i++)
{
//val->ports[i] = 7590+i;
sfds[i] = socket(AF_INET, SOCK_STREAM, 0);
const int optVal = 1;
const socklen_t optLen = sizeof(optVal);
int rtn = setsockopt(sfds[i], SOL_SOCKET, SO_REUSEADDR, (void*) &optVal,
optLen);
if (rtn < 0)
{
perror("Error");
exit(1);
}
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(7590 + i);
ports[i] = i;
servaddr.sin_addr.s_addr = INADDR_ANY;
if (bind(sfds[i], (struct sockaddr*) &servaddr, sizeof(servaddr)) < 0)
{
perror("Error");
exit(1);
}
if (listen(sfds[i], 1) < 0)
{
perror("Error");
exit(1);
}
}
int c = fork();
if (c > 0)
{
val->aid = c;
val->sid = getpid();
kill(getpid(), SIGUSR1);
while (1)
;
}
else if (c == 0)
{
while (1)
;
}
else
{
perror("Error");
exit(1);
}
}
// FILE 2
#include<stdio.h>
#include<signal.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/time.h>
#include<iostream>
#include<netinet/in.h>
#include<sys/select.h>
#include<sys/shm.h>
using namespace std;
struct shm
{
int aid;
int sid;
int bid;
int cid;
int pno;
int portno;
}*val;
int sfds[4];
int count = 4;
void func1(int a)
{
int sfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(7590 + val->portno);
servaddr.sin_addr.s_addr = INADDR_ANY;
const int optVal = 1;
const socklen_t optLen = sizeof(optVal);
cout << val->portno << " vpn " << endl;
int rtn = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*) &optVal,
optLen);
while (bind(sfd, (struct sockaddr*) &servaddr, sizeof(servaddr)) < 0)
{
perror("Error");
}
cout << endl << "Done" << endl;
if (listen(sfd, 1) < 0)
{
perror("Error");
exit(1);
}
for (int i = 0; i < 1; i++)
{
struct sockaddr_in cliaddr;
socklen_t clilen;
int nsfd = accept(sfd, (struct sockaddr*) &cliaddr, &clilen);
send(nsfd, "OkaB", 5, 0);
}
close(sfd);
signal(SIGUSR1, &func1);
kill(val->cid, SIGUSR1);
}
int main()
{
signal(SIGUSR1, &func1);
int shmid = shmget(123456, sizeof(struct shm), IPC_CREAT | 0666);
if (shmid < 0)
{
perror("Error");
}
val = (struct shm*) shmat(shmid, NULL, 0);
val->bid = getpid();
while (1)
;
}
The problem may come from the struct shm definition:
In file 1
struct shm
{
int aid;
int sid;
int bid;
int cid;
int portno;
int pno;
//int ports[4];
}*val;
In other file :
struct shm
{
int aid;
int sid;
int bid;
int cid;
int pno;
int portno;
}*val;
pno and portno are not at the same place.
And as LPs pointed, only one process should create the shared memory (IPC_CREAT)
Related
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 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.
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;
}
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
ANSWER: (because i can't answer my questiong after 7hours :/)
ok, i solved it with this modification:
struct RecvDataModel
{
int sockAddr;
string inData; //old: char *inData;
};
void Client::Recv(int sockAddr, char *inData)
{
cout << inData << endl;
RecvDataModel *outData = new RecvDataModel();
outData->sockAddr = sockAddr;
outData->inData = string(inData);//old outData->inData = inData;
pthread_t rThr;
pthread_create(&rThr, NULL, ProcessData, outData);
}
i think string automatically fixing char* format, otherwise i can't understand nothing!
and now i wanna ask: string and char performance are the same? is there a problem using string instead of char*(excepting pointers-void*-)?
QUESTION:
-inData and sockAddr came from a socket, this is a multiclient chat server- in here, i can send sockAddr to ProcessData but inData can't send! it changes with broken format (like "testDataTextÿñ€ÿñ:¥øv:Y" i sent "testDataText" and it changed). i have tried to create an other char* and copy all in with for loop but at this time if i send "te%s;t" like data, again changes with broken format. what can i do?
struct RecvDataModel
{
int sockAddr;
char *inData;
};
void *ProcessData(void *arg);
void Client::Recv(int sockAddr, char *inData)
{
RecvDataModel * outData = new RecvDataModel();
outData->sockAddr = sockAddr;
outData->inData = inData;
pthread_t rThr;
pthread_create(&rThr, NULL, ProcessData, outData);
}
void *ProcessData(void *arg)
{
RecvDataModel *inData = (RecvDataModel*)arg;
cout << inData->inData << endl;
return 0;
}
inData and sockAddr came from here(Client Class):
#include <winsock2.h>
class Client
{
private:
int mySock;
int sockAddr;
bool logged;
void *listen(void)
{
int numBytes;
char buffer[5120];
while(1)
{
numBytes = recv(mySock, buffer, 5120, 0);
if(numBytes == 0 || numBytes == -1)
{
Drop(mySock);
mySock = 0;
sockAddr = 0;
return 0;
}
Recv(sockAddr, buffer);
memset(buffer, 0, sizeof buffer);
}
return 0;
}
public:
void SetSock(int sock)
{
mySock = sock;
}
void SetSockAddr(int addr)
{
sockAddr = addr;
}
void Logged(bool status)
{
logged = status;
}
int GetSock()
{
return mySock;
}
int GetSockAddr()
{
return sockAddr;
}
bool IsLogged()
{
return logged;
}
static void *Listen(void *arg)
{
return ((Client*)arg)->listen();
}
static void Recv(int sockAddr, char *inData);
static void Drop(int sockAddr);
};
and all of main.cpp
#define PORT 9696
#define MAXCONN 9999
#define BACKLOG 128
#include <winsock2.h>
#include <pthread.h>
#include <iostream>
#include "Client.cpp"
using namespace std;
struct RecvDataModel
{
int sockAddr;
char *inData;
};
Client m_Clients[MAXCONN];
void *AcceptClients(void *arg);
void *HandleClient(void *arg);
void *DropClient(void *arg);
void *ProcessData(void *arg);
void Client::Recv(int sockAddr, char *inData)
{
cout << inData << endl;
RecvDataModel *outData = new RecvDataModel();
outData->sockAddr = sockAddr;
outData->inData = inData;
pthread_t rThr;
pthread_create(&rThr, NULL, ProcessData, outData);
}
void Client::Drop(int sockAddr)
{
pthread_t dThr;
pthread_create(&dThr, NULL, DropClient, (void*)sockAddr);
}
int main()
{
/* WinSock initialization::START */
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
{
cout << "WSA initialization failed!";
WSACleanup();
return 1;
}
/* WinSock initialization::END */
SOCKET m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//--> TCP Socket: socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
//--> UDP Socket: socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
if(m_Socket == INVALID_SOCKET)
{
cout << "Cannot create server socket!";
WSACleanup();
return 1;
}
sockaddr_in m_Inf;
m_Inf.sin_family = AF_INET;
m_Inf.sin_port = htons(PORT);
m_Inf.sin_addr.s_addr = INADDR_ANY;
if(bind(m_Socket, (sockaddr*)(&m_Inf), sizeof(m_Inf)) == SOCKET_ERROR)
{
cout << "Cannot bind server socket!";
WSACleanup();
return 1;
}
if(listen(m_Socket, BACKLOG) == SOCKET_ERROR)
{
cout << "Server socket cannot start listening!";
WSACleanup();
return 1;
}
for(int i = 0; i < MAXCONN; i++)
{
m_Clients[i].SetSock(0);
}
cout << "Listening for connections..." << endl;
pthread_t mThr;
pthread_create(&mThr, NULL, AcceptClients, (void*)m_Socket);
cin.ignore();
cin.get();
cin.clear();
WSACleanup();
return 0;
}
void *AcceptClients(void *arg)
{
int m_Socket = (int)arg;
while(1)
{
sockaddr_in Sin;
int SinLen = sizeof(Sin);
SOCKET c_Socket = accept(m_Socket, (sockaddr*)(&Sin), &SinLen);
if(c_Socket == INVALID_SOCKET)
{
cout << "A connection initialized but dropped! (invalid socket)" << endl;
}
else
{
pthread_t hThr;
pthread_create(&hThr, NULL, HandleClient, (void*)c_Socket);
}
}
return 0;
}
void *HandleClient(void *arg)
{
int inSock = (int)arg;
bool avaibleFound = false;
int lastLooked = 0;
int avaibleAddr = -1;
while(!avaibleFound)
{
avaibleFound = true;
if(lastLooked != MAXCONN)
{
if(m_Clients[lastLooked].GetSock() == 0)
{
avaibleAddr = lastLooked;
avaibleFound = true;
}
else
{
lastLooked += 1;
avaibleFound = false;
}
}
else
{
avaibleAddr = -1;
avaibleFound = true;
}
}
if(avaibleAddr != -1)
{
m_Clients[avaibleAddr].SetSockAddr(avaibleAddr);
m_Clients[avaibleAddr].SetSock(inSock);
cout << "Socket(#" << inSock << ") connected." << endl;
pthread_t cThr;
pthread_create(&cThr, NULL, &Client::Listen, (void*)&m_Clients[avaibleAddr]);
}
else
{
send(inSock, "11", 2, 0);//11: Server is full!
closesocket(inSock);
}
return 0;
}
void *DropClient(void *arg)
{
int inSock = (int)arg;
cout << "Socket(#" << inSock << ") disconnected." << endl;
return 0;
}
void *ProcessData(void *arg)
{
RecvDataModel *inData = (RecvDataModel*)arg;
cout << inData->sockAddr << inData->inData << endl;
delete inData;
return 0;
}
i have already post a question like this but nobody answered, this is very important for me sorry :L
Add the following into your listen function just before the call to Recv:
buffer[numBytes]=0;
This way, you'll be sure that the string you're trying to print is null-terminated, and you'll see no garbage coming from the uninitialized buffer for the first time (yes, you memset it later, but it does not help for the first packet).
I followed this nice tutorial to create a simple non-blocking server using select() function. Here's what I have:
void setNonBlocking(int socketFD) {
int x;
x = fcntl(socketFD,F_GETFL,0);
fcntl(socketFD,F_SETFL,x | O_NONBLOCK);
return;
}
int initialize(char * port) {
int yes = 1;
listener = socket(PF_INET,SOCK_STREAM, 0);
if (listener < 0) {
perror("listener");
exit(EXIT_FAILURE);
}
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
setNonBlocking(listener);
struct sockaddr_in server_address;
memset((char *) &server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
// server_address.sin_addr.s_addr = htonl(INADDR_ANY);
inet_aton("132.65.151.39",&(server_address.sin_addr));
server_address.sin_port = htons(atoi(port));
if (bind(listener, (struct sockaddr *) &server_address,
sizeof(server_address)) < 0 ) {
perror("bind");
close(listener);
exit(EXIT_FAILURE);
}
listen(listener,BACKLOG);
maxSocket = listener;
memset((char *) &clientQueue, 0, sizeof(clientQueue));
return 0;
}
void readSockets() {
int i;
cout << "in readSockets()" << endl;
if (FD_ISSET(listener,&sockets))
createConnection();
for (i = 0; i < 5; i++) {
if (FD_ISSET(clientQueue[i],&sockets))
readData(i);
} /* for (all entries in queue) */
}
int main(int argc, char* argv[]) {
if (argc != 2) {
fprintf(stderr,"usage: server port\n");
exit(EXIT_FAILURE);
}
if (initialize(argv[1]) != 0) {
exit(EXIT_FAILURE);
}
struct timeval timeout;
int value;
printf("server: waiting for connections...\n");
while(1) { // main accept() loop
build_select_list();
timeout.tv_sec = 1;
timeout.tv_usec = 0;
value = select(maxSocket, &sockets, (fd_set *) 0,(fd_set *) 0, &timeout);
if (value == -1) {
perror("select");
exit(EXIT_FAILURE);
}
if (value == 0) {
printf("%d",value);
fflush(stdout);
} else{
cout << "Value is " << value << endl;
readSockets();
}
}
return EXIT_SUCCESS;
}
My problem is simple - select always returns 0, meaning it does not get or does not respond to a new connection. I checked my client a day ago with a blocking more simple server and it did work, so I don't think its the porblem.
You'll notice that I tried both IP addresses:
server_address.sin_family = AF_INET;
// server_address.sin_addr.s_addr = htonl(INADDR_ANY);
Can anyone please help me? I feel lost :)
Please refer to man select, first parameter should be number of highest descriptor + 1, so in your case:
value = select(maxSocket + 1, &sockets, (fd_set *) 0,(fd_set *) 0, &timeout);