Go back N protocol implememtation - sockets
I am implementing Go back N protocol in C.I keep a char buffer and append the header informationa and data and send it to the server from the client process.
When I keep window size less than 10, the sequence number takes the value 1-9and occupies only one byte in the buffer. When the window size is >= 10 , sequence number may 1 or 2 bytes in the character array. So I am appending length of sequence number also as a header information. That time I am getting some random data written in the output file at the server. Whereas for window size less than 10 I coded without adding sequence no. length info. Everything works fine that time.
The codes are quiet exhaustive. Yet,
Can anybody suggest any corrections to be made in the code?
client code for window size 10:-
#include<stdio.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<netdb.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<time.h>
#include<sys/time.h>
unsigned short int checksum_2(void *buffer,unsigned int len,unsigned short int seed)
{
unsigned char *buf1 = (unsigned char*)buffer;
int i;
for(i=0;i<len;i++)
{
seed+=(unsigned int)(*buf1++);
}
//fold 32-bit sum to 16 bit
while(seed>>16)
seed = (seed & 0xFFFF)+ (seed>>16);
return seed;
}
unsigned short int checksum(unsigned char * buff,unsigned int count)
{
register unsigned int sum = 0;
//main summing loop
while(count >1)
{
sum += *((unsigned short int*) buff);
(buff)++;
count = count -2;
}
//add left over byte if any
if(count>0)
{
sum += *((unsigned char *)buff);
}
//fold 32-bit sum to 16 bit
while(sum>>16)
sum = (sum & 0xFFFF)+ (sum>>16);
return (~sum);
}
char* rand_corrupt(unsigned char* buff)
{
int n = strlen(buff);
char* str_temp = (char*)calloc(1,n); //allocate memory for a string
int i;
int num;
num = rand() %100;
if(num>95)
{
for(i=0;i<strlen(buff);i++)
{
buff[i] = buff[i]+1;
}
}
strcpy(str_temp,buff);
return str_temp;
}
char *itoa(long i,char *s,int dummy_radix)
{
sprintf(s,"%ld",i);
return s;
}
void rand_wait()
{
int num;
int i;
num = rand() %100;
if(num<5)
{
for(i=0;i<10;i++)
{
sleep(1);
}
}
return;
}
int
main (int argc, char **argv)
{
int sock,length,n;
struct sockaddr_in server,from;
struct hostent *hp;
long int packets =0;
clock_t t; //to measure CPU time
struct timeval start,end; //to measure actual execution time
struct timeval timer; //for the timer implementation
double time_diff;//to measure the timer for the execution time of code
unsigned short int check;
void* buff;
printf("initializing 2 d array\n");
char buf[1024][1024]={0};
printf("initialisation failed\n");
int nread[1024] = {0,};
char new_buff[65535]={0, };
char ack_buf[65535]={0, };
char* temp;
char checksum_info[1024]={0, } ;
char bytes_info[1024] = {0, } ;
unsigned short int bytes_len;
char bytes_len_str[1024]={0, };
char seqnum[10] = {0,};
int seq_no;
char current;
char data_1[75535]={0, };
unsigned short int check_length;
char check_len_str[1024]={0, };
char ack_check_len[1024]={0, };
unsigned short int ack_checksum_len;
char ack_check[65535]={0, };
unsigned short int ack_checksum;
char temp_buf[65535]={0, };
char temp_buffer[655]={0,};
unsigned short int actual_checksum;
unsigned short int length1;
char content[65535]={0, };
int i,j;
char end_flag =0; //to mark the end of file or error occured while reading file
int total_len[1024]={0,};
char data[1024][6553]= {0,};
char *tmp = NULL;
int msec,trigger;
clock_t difference,initial;
char ack_seqlen_char[8]= {0,};
int ack_seqlen;
int ack_seq;
char ack_seq_char[10] ={0,};
int seqnum_len;
char seqlen_char[10] = {0,};
t = clock();
gettimeofday(&start,NULL);
buff = calloc(1,1024);//allocating memory for message buffer
if(buff == NULL)
{
printf("memory allocation failedi\n");
return 1;
}
temp = calloc(1,65535); //allocating memory for new message
if(temp == NULL)
{
printf("memory allocation failed\n");
return 1;
}
// checking if hostname and the port address is provided //
if(argc!=3)
{
printf("insufficient arguments\n");
exit(1);
}
//create a socket//
sock = socket(AF_INET,SOCK_DGRAM,0);
if(sock<0)
{
printf("error in opening socket\n");
return 1;
}
//to get the hostname of the system or the machine//
hp= gethostbyname(argv[1]);
if(hp==0)
{
printf("Unknown host\n");
return 1;
}
//build the server's IP address //
bzero((char *)&server,sizeof(server));
bcopy((char*)hp->h_addr,(char *)&server.sin_addr,hp->h_length);
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[2]));
length = sizeof(server);
/*open the file that we wish to transfer*/
FILE *fp = fopen("alice.txt","rb");
if(fp==NULL)
{
printf("file open error");
return 1;
}
fseek(fp,0,SEEK_END); //if exists read the size of the file
size_t file_size = ftell(fp);
fseek(fp,0,SEEK_SET);
printf("size of the file is %d\n", file_size);
/*find the number of packets*/
if(file_size == 0)
{
packets = 0;
}
else
{
packets = (file_size/1024)+1 ;
}
/*send the number of packets to the server*/
itoa(packets,(char*)buff,10);
printf("packets =%s\n",(char*)buff);
n= sendto(sock,buff,1024,0,(struct sockaddr *)&server,sizeof(struct sockaddr));
if(n<0)
{
printf("error in sending message to the server");
return 1;
}
int loop =1;
/*Read data from file and send it*/
int packetNum = 0;
int N = 10;
int base = 1;
int nextseqnum =1;
int sequence;
int seqnum_next = 1;
while(1)
{
while(nextseqnum<base+N) //send N consecutive packets
{
memset(buf[nextseqnum], 0, 65535); //clear the contents of buf before fread
memset(seqnum,0,10);
memset(seqlen_char,0,10);
memset(checksum_info,0,1024);
memset(check_len_str,0,1024);
memset(bytes_info,0,1024);
memset(bytes_len_str,0,1024);
memset(data[nextseqnum],0,6553);
/*First read file in chunks of 1024 bytes */
nread[nextseqnum] = fread(buf[nextseqnum],1,1024,fp);
printf("Bytes read %d\n",nread[nextseqnum]);
/*if read was success ,send data*/
if(nread[nextseqnum]>0)
{
printf ("I am HERE\n");
check = checksum(buf[nextseqnum],nread[nextseqnum]); //calculate the checksum
printf("checksum is %d\n",check);
itoa(check,checksum_info,10); //convert checksum into string
check_length = strlen(checksum_info); //calculate the length of the checksum
itoa(check_length,check_len_str,10); //convert the checksum lenght to string form
itoa(nread[nextseqnum],bytes_info,10); //the data length in string format
bytes_len = strlen(bytes_info);
itoa(bytes_len,bytes_len_str,10);
itoa(seqnum_next,seqnum,10); //combine seq no,checksum and the data content into one packet
printf("sequence number is %s\n",seqnum);
seqnum_len = strlen(seqnum); //getting the length of the sequence
itoa(seqnum_len,seqlen_char,10); //converting it into string format
strncat(data[nextseqnum],seqlen_char,strlen(seqlen_char));
strncat(data[nextseqnum],seqnum,strlen(seqnum));
strncat(data[nextseqnum],check_len_str,(strlen(check_len_str)));
strncat(data[nextseqnum],checksum_info,(strlen(checksum_info))); //adding checksum
strncat(data[nextseqnum],bytes_len_str,strlen(bytes_len_str)); //adding data length
strncat(data[nextseqnum],bytes_info,strlen(bytes_info)); //adding the data length info
j= seqnum_len+3+bytes_len+check_length;
for(i=0;i<nread[nextseqnum];i++)
{
data[nextseqnum][j] = buf[nextseqnum][i];
j++;
}
total_len[nextseqnum] = nread[nextseqnum]+3+bytes_len+check_length;//finding the total length
data[nextseqnum][total_len[nextseqnum]] = '\0';
n= sendto(sock,data[nextseqnum],total_len[nextseqnum],0,(struct sockaddr *)&server,sizeof(struct sockaddr));///send the data packet after adding the header info
if(n<0)
{
printf("error in sending message to the server");
fclose(fp);
return 1;
}
if(nextseqnum == base)
{
msec = 0;
trigger = 50; /*50 ms*/
initial = clock(); /*start the timer*/
}
nextseqnum++;
seqnum_next = nextseqnum%N;
if(seqnum_next == 0)
{
seqnum_next = N;
}
sleep(1);
}
/*There is something tricky going on with the read..
* Either there was error ,or we reached end of file.
*/
else
{
if(feof(fp))
printf("End of file\n");
if(ferror(fp))
printf("Error reading\n");
end_flag = 1; //set the flag that it has reached EOF or encountered error
break;
}
}
while(1) //wait for the acknowledgement for the sent packets till timeout , here timer value is set to 50 ms
{
difference = clock()-initial;
msec = difference*1000/CLOCKS_PER_SEC;
if(msec<trigger) //if it is not timeout then receive the ack packets
{
memset(ack_buf, 0, 65535); //clear the contents of ack_buf
memset(ack_check_len,0,1024);
memset(ack_check,0,65535);
memset(content,0,65535);
memset(temp_buf,0,65535);
//printf ("Receiving packet\n");
n = recvfrom(sock,ack_buf,1024,MSG_DONTWAIT,&server, &length); //receive the ack from the server
if(n>0)
{
j=0;
for(i=0;i<1;i++)
{
temp_buffer[j] = ack_buf[i];
j++;
}
temp_buffer[j] = '\0';
strcpy(ack_seqlen_char,temp_buffer);//get the length of the ack sequence //number
ack_seqlen = atoi(ack_seqlen_char); //converting it to int
j=0;
for(i=1;i<1+ack_seqlen;i++)
{
ack_seq_char[j]= ack_buf[i];
j++; //next bytes till i=ack_seqlen will be sequence number
}
seq_no = atoi(ack_seq_char);
printf("Ack received for the sequence number %d\n",seq_no);
j =0;
for(i=1+ack_seqlen;i<2+ack_seqlen;i++) //next byte will have the length of checksum
{
temp_buf[j] = ack_buf[i]; //extracting the checksum length
j++;
}
temp_buf[j] = '\0'; //ending the string with a null character
strcpy(ack_check_len,temp_buf); //length of checksum will be in string format
ack_checksum_len = atoi(ack_check_len); //convert it into int
j = 0;
for(i=2+ack_seqlen;i<(2+ack_seqlen+ack_checksum_len);i++) //extract the checksum
{
ack_check[j] = ack_buf[i];
j++;
}
ack_check[j] ='\0';
ack_checksum = atoi(ack_check); //the checksum will be in string format,convert it into the integer format
j=0; //extract the content i.e the actual ack message
while(i<n)
{
content[j] = ack_buf[i];
i++;
j++;
}
content[j] ='\0';
length1 = strlen(content);
actual_checksum = checksum(content,length1);//calculate the actual checksum
printf("checksum of the ack received is %d\t and the checksum of the ack sent is %d\n",actual_checksum,ack_checksum);
if(actual_checksum == ack_checksum) //if the ack is not corrupt then update the base
{
printf("successfully recived packet %d\n",seq_no);
base =seq_no+1;
if(base == nextseqnum) //go to sending next series of packets
{
printf ("base is %d\n", base);
break;
}
else
{
initial = clock(); //start timer for next in-flight packet
}
}
else //if it is a corrupt ack
{
printf("Ack corrupted,wait till timeout\n");
}
} else {
if (end_flag == 1) {
printf ("Reached END\n");
break;
}
}
}
else //if the timer is out, resend the packet from the packet with seqno
// base till nextseqnum-1,start timer
{
initial = clock();
sequence = base;
while(sequence <= nextseqnum-1)
{
n= sendto(sock,data[sequence],total_len[sequence],0,(struct sockaddr *)&server,sizeof(struct sockaddr));///send the data packet after adding the header info
if(n<0)
{
printf("error in sending message to the server");
fclose(fp);
return 1;
}
sleep(0.5);
}
}
}
if(end_flag == 1) //if there had been an error in reading file of EOF had reached break out of
// the outermost while loop
{
printf ("I am at the END\n");
break;
}
}
printf ("Sending finish packet\n");
strcpy(buff,"Finish");
n= sendto(sock,buff,1024,0,(struct sockaddr *)&server,sizeof(struct sockaddr));
if(n<0)
{
printf("error in sending message to the server");
return 1;
}
fclose(fp); //close the file to complete the transmission
t = clock()-t;
gettimeofday(&end,NULL);
double time_taken = ((double)t)/CLOCKS_PER_SEC; //in secconds
printf(" The CPU time for transmission %f seconds \n",time_taken);
double delta = ((end.tv_sec - start.tv_sec)*1000000u+ end.tv_usec - start.tv_usec)/1.e6;
printf("The actual execution time took %f seconds\n", delta);
close(sock); //close api tries to complete the transmission if there is data waiting to be transmitted
return 0;
}
Related
Received Data Zeroed Out After Encountering First Byte Equal to Zero
Summarize the Problem: I wrote a userspace SPI driver in linux for the NRF24L01+ transceiver. My goal is to send files to a server. A jetson nano is the sender, and a raspberry pi 3b+ the receiver. Both the spi and nano are running Linux. I can consistently send packets and receive acknowledgements. However, the issue is whenever I send a packet such as 0x ff ee dd 00 cc bb aa the receiver only receives the packet 0x ff ee dd 00 00 00 00. So what is happening is that whenever the first byte encountered is zero, the rest of the packet becomes zero. This causes the files I send to become corrupted. I was able to reproduce this bug with a char array having a similar pattern. I noticed this trend when I printed out the file contents I was sending on the transmitter and receiver. What I've tried: I've tried altering my SPI read function. What I thought was happening was the chip select line was being flipped high early. This did not work, I got the same results. I've printed the packets before calling the ioctl() function from the transmitter and the packet remains intact. I've printed the return value of the ioctl() function to see how many bytes I was receiving and sending. I was sending 31 bytes from the transmitter, and receiving 32 bytes from the receiver. So it doesn't look like my reads and sends are failing. If I had a logic analyzer my next step would be to check the SPI pins on the transmitter, but unfortunately I don't have one. I've added a 10uF decoupling capacitor on the transceivers and that sped up communication. Show Some Code: Receiver side: /** * Reads the payload when data pipe * is available. * * spi_dev_fd: file descriptor for spi device. * */ int nrf_rx_read(int spi_dev_fd, char * payload, int * pipe, int * bytes) { int pipe_temp, rtn; // TODO: Add timeout. do { rtn = nrf_rx_pipe_available(spi_dev_fd, &pipe_temp); }while(rtn != 0); if(rtn == 0) { char status; if(bytes != NULL) { char size; spi_read_msg(spi_dev_fd, R_RX_PL_WID, &status, &size, 1); *bytes = (int) size; } spi_read_msg(spi_dev_fd, R_RX_PAYLOAD , &status, payload, (int) NUM_PAYLOAD_BYTES); *pipe = pipe_temp; char msg; msg = RX_DR; spi_send_msg(spi_dev_fd, W_REGISTER | STATUS, &msg, 1); return 0; } return 1; } bool nrf_rx_pipe_available(int spi_dev_fd, int * pipe) { char addr = NOP; char status; spi_read_msg(spi_dev_fd, addr, &status, NULL, 0); if((status & RX_DR) > 0) { *pipe = (status >> RX_P_NO) & 0x07; if(*pipe > 5) { return 1; } return 0; } return 1; } int spi_read_msg(int spi_dev_fd, char addr, char * status, char * copy_to, int len) { char data_buffer; char recv_buffer[len + 1]; struct spi_ioc_transfer xfer; memset(&xfer, 0, sizeof(xfer)); memset(&recv_buffer, 0, sizeof(recv_buffer)); data_buffer = addr; xfer.tx_buf = (unsigned long) &data_buffer; xfer.rx_buf = (unsigned long) recv_buffer; xfer.len = len + 2; xfer.bits_per_word = 8; xfer.speed_hz = 1000000; xfer.cs_change = 0; xfer.rx_nbits = len * 8; xfer.tx_nbits = 8; int res = ioctl(spi_dev_fd, SPI_IOC_MESSAGE(1), xfer); if(res > 0) { status[0] = recv_buffer[0]; if(copy_to != NULL) { string temp = string(recv_buffer); temp = temp.substr(1); strncpy(copy_to, temp.c_str(), len); } // debug code for(int i = 0; i < len; ++i) { printf("copy_to: %x \n ", copy_to[i]); } // end debug code. } return res; } Transmitter side: /** * Function to load a payload and send a packet. * * * spi_dev_fd: file descriptor for spi device. * */ int nrf_tx_send_packet(int spi_dev_fd, char * payload, int len) { int rtn; // Put low so we can add the payload. gpio_set_value((unsigned int) GPIO_CE, (unsigned int) GPIO_LVL_LOW); // Set a new payload. nrf_tx_new_payload(spi_dev_fd, payload, len); // Start tx transmission. gpio_set_value((unsigned int) GPIO_CE, (unsigned int) GPIO_LVL_HIGH); do { rtn = nrf_tx_pending_send(spi_dev_fd); if(rtn == 2) { char clr = MAX_RT; spi_send_msg(spi_dev_fd, W_REGISTER | STATUS, &clr, 1); } }while(rtn != 1); // Go back to standby mode gpio_set_value((unsigned int) GPIO_CE, (unsigned int) GPIO_LVL_LOW); // Setting chip enable to 0. char reg = W_REGISTER | STATUS; char val = RX_DR | TX_DS | MAX_RT; spi_send_msg(spi_dev_fd, reg, &val, 1); return 0; } int spi_send_msg(int spi_dev_fd, char addr, char * data, int len) { char data_buffer[len + 1]; char recv_buffer; struct spi_ioc_transfer xfer; memset(&xfer, 0, sizeof(xfer)); memset(&recv_buffer, 0, sizeof(recv_buffer)); data_buffer[0] = addr; for(int i = 1; i < len + 1; ++i) { data_buffer[i] = data[i-1]; printf("databuffer[i]: %x \n", data_buffer[i]); } xfer.tx_buf = (unsigned long) data_buffer; xfer.rx_buf = (unsigned long) NULL; xfer.len = len + 1; xfer.bits_per_word = 8; xfer.speed_hz = 1000000; xfer.cs_change = 0; //xfer.rx_nbits = 8; xfer.rx_nbits = 0; xfer.tx_nbits = (8 * len) + 8; int res = ioctl(spi_dev_fd, SPI_IOC_MESSAGE(1), xfer); printf("res: %i \n", res); return res; } I tried to add all the relevant code, sorry if it is a bit much. Main thing to look at is the send and receive functions. They all work as expected until I encounter the zeroed out byte. If I am missing any information that can help someone out please let me know and I can add it. I think the send and receive functions are the most important however. I'm able to set and read the registers of the transceiver.
I can send files now! The fix was done in spi_read_msg() function. The problem was I was converting the buffer received to a string, which caused the data to be trimmed when the byte 0x00 was encountered. This is also equivalent to the null terminating character. Receiver code: int spi_read_msg(int spi_dev_fd, char addr, char * status, char * copy_to, int len) { char data_buffer; char recv_buffer[len + 1]; struct spi_ioc_transfer xfer; memset(&xfer, 0, sizeof(xfer)); memset(&recv_buffer, 0, sizeof(recv_buffer)); data_buffer = addr; xfer.tx_buf = (unsigned long) &data_buffer; xfer.rx_buf = (unsigned long) recv_buffer; xfer.len = len + 2; xfer.bits_per_word = 8; xfer.speed_hz = 1000000; xfer.cs_change = 0; xfer.rx_nbits = len * 8; xfer.tx_nbits = 8; int res = ioctl(spi_dev_fd, SPI_IOC_MESSAGE(1), xfer); if(res > 0) { status[0] = recv_buffer[0]; if(copy_to != NULL) { for(int i = 0; i < len; ++i) { copy_to[i] = recv_buffer[i + 1]; } } } return res; }
low cpu-usage way to monitor connection to localhost
It seems a nonblocking connect to localhost always fails right away then poll() returns immediately with POLLIN flag set in revents. That prevents CPU enter a blocking state and the entire system runs in quite high cpu usage. PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1470 panruoc+ 20 0 12956 1956 1820 S 26.2 0.0 2:09.49 zz1 Any suggestion is appriciated. Here is my code of testing int main(int argc, char *argv[]) { struct sockdesc { char *host; int port; int sockfd; }; struct sockdesc sdes[] = { {"localhost", 6000}, {"111.206.239.212", 6000}, }; unsigned int i; for(i = 0; i < 2; i++) { tcp_connect(sdes[i].host, sdes[i].port, &sdes[i].sockfd); printf("sockfd = %d, %d\n", sdes[i].sockfd, errno); } if(!nonblocking) return 0; struct pollfd pollfds[2]; pollfds[0].fd = sdes[0].sockfd; pollfds[1].fd = sdes[1].sockfd; pollfds[0].events = POLLIN; pollfds[1].events = POLLIN; int conns; for(conns = 0; conns != 3; ) { int nfds = poll(pollfds, 2, -1); if(nfds <= 0) exit(1); for(i = 0; (int)i < nfds; i++) { if(pollfds[i].revents) { if(pollfds[i].revents & POLLIN) conns |= i; printf(" fd = %d, revents = 0x%04x\n", sdes[i].sockfd, pollfds[i].revents); } } } return 0; } BR, Ruochen
Your for-loop looks suspicious: for(conns = 0; conns != 3; ) { When does conns ever become three? It seems like your intent is here: if(pollfds[i].revents & POLLIN) conns |= i; But if i is 0 for the first socket, conns |= i will not change the value. And when both sockets have data available, your poll call will start returning immediately, but you are stuck in an infinite loop. Hence, high cpu overhead. It appears your code's intent is to stay in a loop until both sockets have data available to read. Then break out of the loop then. So I suspect you really meant this: conns |= (i+1); There's other problems as well. poll returns the number of valid socket descriptors. Hence this line; for(i = 0; (int)i < nfds; i++) { So if the socket associated with pollfds[1] has data available, nfds will only be 1. Hence, your loop will only evaluate if pollfds[0] has data. Let's clean your code up: int ready_set = 0x00; int all_ready_set = 0x03; int num_sockets = 2; while (ready_set != all_ready_set) { int nfds = poll(pollfds, 2, -1); if(nfds <= 0) { // I would not actually exit. If a socket gets closed locally, you would have a valid and expected error, but maybe that can't happen in your program exit(1); } for (i = 0; i < num_sockets; i++) { if (pollfds[i].revents & POLLIN) { int mask = 0x01 << i; pollfds[i].events = 0; // stop listening for events on this socket ready_set |= mask; } } }
I'm not sure if my netfilter is working or not
I'm trying to make a LKM netfilter that drops incoming packets if the number of packets arrived exceeds a certain limit. There are five ports that the packets comes through, and netfiltering is done for each of those ports. Here's part of my LKM netfilter (it uses procfs to write from user program): #define MAX_PORT 5 static unsigned short int port[MAX_PORT]; static unsigned long limit; static char char_limit[256]; static unsigned long data_count[MAX_PORT]; bool check_port(unsigned short int); static unsigned int my_hook_fn( void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { struct iphdr *ip = ip_hdr(skb); struct tcphdr *th = tcp_hdr(skb); unsigned int source, dest; if(!skb) return NF_ACCEPT; if(ip->protocol==IPPROTO_TCP) { source = htons((unsigned short int) th->source); dest = htons((unsigned short int) th->dest); printk(KERN_ALERT "source: %u, destination: %u\n", source, dest); if(!check_port(source)) { printk(KERN_ALERT "packet dropped!\n"); return NF_DROP; } } return NF_ACCEPT; } bool check_port(unsigned short int source) { int i = 0; bool found = false; while(!found && i < MAX_PORT) { if(port[i] == source) found = true; else if(port[i] == 0) { port[i] = source; found = true; } i++; } i--; data_count[i]++; if(data_count[i] >= limit) { data_count[i] = limit; printk(KERN_ALERT "port %hu has reached the limit!\n", port[i]); return false; } return true; } static struct nf_hook_ops my_nf_ops = { .hook = my_hook_fn, .pf = PF_INET, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_FIRST, }; In my hook function, the NF_DROP seems to be correctly returned. However, the result in my user space program shows that it's not. Next is my user space program; this produces results in txt files. void *thread_recv(void *arg); #define MAX_CON 5 #define BUF_SIZE 200 int port[MAX_CON]; char ip[20]; int sock[MAX_CON]; void error_handling(char *msg); void main(){ int i; unsigned long limit; char char_limit[256]; FILE *fp; printf("packet limit : "); scanf("%lu", &limit); sprintf(char_limit, "%lu", limit); fp = fopen("/proc/myproc/myproc", "w"); if(fp == NULL) printf("unable to open myproc\n"); else fprintf(fp, "%s", char_limit); fclose(fp); struct sockaddr_in serv_adr; pthread_t thread_id[MAX_CON]; printf("ip :\n"); scanf("%s",ip); printf("<port> <port> <port> <port> <port>\n"); scanf("%d %d %d %d %d", &(port[0]), &(port[1]), &(port[2]), &(port[3]), &(port[4])); printf("%s %d\n", ip, port[0]); for(i=0;i<5;i++){ sock[i]=socket(PF_INET, SOCK_STREAM, 0); if(sock[i]==-1) error_handling("socket() error"); memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family=AF_INET; serv_adr.sin_addr.s_addr=inet_addr(ip); serv_adr.sin_port=htons(port[i]); if(connect(sock[i], (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1) error_handling("connect() error"); else printf("port %d connected\n", port[i]); pthread_create(&(thread_id[i]),NULL, thread_recv,(void*)&(sock[i])); } while(1); // do infinitely, so user should end by their own. Ctrl + C } void *thread_recv(void *arg){ int clnt_sock= *(int*)arg; // get socketnumber from main int str_len=0, i; // recv byte length int tport=0; // portnumber matching socketnumber char msg[BUF_SIZE]; time_t timer; struct tm *t; struct timespec spec; unsigned long ms; FILE *fp; char filename[20]={NULL}; for(i=0;i<5;i++) if(sock[i]==clnt_sock) tport=port[i]; sprintf(filename,"%d.txt",tport); fp=fopen(filename,"w+"); printf("%d port thread run\n", tport); while((str_len=read(clnt_sock, msg, sizeof(msg)))){ msg[str_len]=NULL; timer= time(NULL); t= localtime(&timer); clock_gettime(CLOCK_REALTIME, &spec); ms = round(spec.tv_nsec / 1.0e6); fprintf(fp,"%d:%d:%d.%lu %d %s\n",t->tm_hour,t->tm_min,t->tm_sec,ms,str_len,msg); } fclose(fp); } void error_handling(char *msg){ fputs(msg, stderr); fputc('\n', stderr); exit(1); } Within the thread_recv function, a txt file is created with its name as the matching port number. What I was expecting from this was that once packet is dropped, the resulting txt file will stop being updated. For example, if the limit is 10, then only 10 socket information will be written to the file. But even when the ports have reached the limit, they keep updating the resulting txt files. Does that mean that the packets have not been dropped properly?
select socket call send and recv synchronization
I am using the select call and accepting the connection from "X" no of clients. I made duplex connection i.e. server to client and client to server. When connection is established between 2 entities ,I am going to send data in chunks from one entity to other. During send I read one file in chunks and send the data in chunks. while(file_size !=0) { read_bytes = read(fd, buff, sizeof(buff)); cnt_ = send(_sock_fd,buff,actually_read,0); file_size = file_size - cnt_; printf("total sent remaining %d : %d\n",size,actually_read); } while at receiver side //First I send the header which contain size it got accepted fine but during the following send call I used "get_readable_bytes" (Using ioctl) which returns me the no of bytes arrived at socket `while(size != 0) { int test_ = 0; while(((cnt_= get_readable_bytes(_sock_fd))== 0) )//&& test_ == 0 { cnt_= get_n_readable_bytes(_sock_fd); printf("Total bytes recved %d\n",cnt_); //test_ = test_ + 1; } while(cnt_ != 0) { actually_read = recv(_sock_fd, buff, sizeof(buff),0); int _cnt = get_n_readable_bytes(_sock_fd); printf("Total bytes recved %d\n",cnt_-_cnt); write(_fd,buff,actually_read); cnt_ = cnt_ - actually_read; test_ = 0; } `Now the problem is 1.During this execution of receive function control automatically go to the select function and it tries to execute whole receive function again so is there any way to synchronize the sender and receivers such that when the sender complete then start receiver or as soon as sender start receiver ? 2.And how do I maintain the count of bytes sent and received. and this is my select call `is_read_availble = select(maxfd + 1,&read_set,NULL,NULL,&timeout)` with timeout 10sec.
Sketch of the kind of buffer code you need. (To allow partial reads/writes, the buffers need to be persistent between calls) BTW: you really need to handle the -1 return from read() and write() because they would seriously disturb your buffer-bookkeeping. EINTR + EAGAIN/EWOULDBLOCK is very common. struct buff { unsigned size; unsigned bot; unsigned top; char *buff; }; struct buff bf = {0,0,0,NULL}; initialisation: bf.buff = malloc(SOME_SIZE); /* ... error checking omitted */ bp.size = SOME_SIZE; bp.bot = bp.top =0; reading: unsigned todo; int rc; /* (maybe) shift the buffer down to make place */ todo = bf.top - bf.bot; if (todo) { memmove (bf.buff, bf.buff + bf.bot, todo); bf.top = todo; bf.bot = 0; } todo = bf.size - bf.top; if (!todo) { /* maybe throttle? ... */ return; } rc = read (fd, bf.buff+bp.top, todo); /* ... error checking omitted */ if (rc == -1) switch (errno) {...} else if (rc == 0) {...} else { total_read += rc; bp.top += rc; } writing: unsigned todo; int rc; todo = bf.top - bf.bot; if (!todo) { /* maybe juggle fd_set ... */ return; } rc = write (fd, bf.buff+bp.bot, todo); /* ... error checking omitted */ if (rc == -1) switch (errno) {...} else if (rc ==0) { ...} else { bp.bot += rc; total_written += rc; if (bp.bot == bp.top) bp.bot = bp.top =0; } /* ... this is the place to juggle the fd_set for writing */
C++ code to find BSSID OF associated network
Hello I've written the following code which is a part of a project. It is used to find the ESSID of the current associated network. But it has a flaw: it also the displays the ESSID of the network with which I am not associated i.e. if I try to associate myself with a wireless n/w and if it is unsuccessful i.e. NO DHCP OFFERS ARE RECEIVED, then also it will display the that ESSID with which I have made my attempt. Could anyone give me an ioctl call to find the BSSID of current associated wireless n/w?. In my opinion it is the only way with which I a can mark b/w associated and non associated. CODE:- int main (void) { int errno; struct iwreq wreq; CStdString result = "None"; int sockfd; char * id; char ESSID[100]; memset(&wreq, 0, sizeof(struct iwreq)); if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { fprintf(stderr, "Cannot open socket \n"); fprintf(stderr, "errno = %d \n", errno); fprintf(stderr, "Error description is : %s\n",strerror(errno)); return result ; } CLog::Log(LOGINFO,"Socket opened successfully"); FILE* fp = fopen("/proc/net/dev", "r"); if (!fp) { // TBD: Error return result; } char* line = NULL; size_t linel = 0; int n; char* p; int linenum = 0; while (getdelim(&line, &linel, '\n', fp) > 0) { // skip first two lines if (linenum++ < 2) continue; p = line; while (isspace(*p)) ++p; n = strcspn(p, ": \t"); p[n] = 0; strcpy(wreq.ifr_name, p); id = new char[IW_ESSID_MAX_SIZE+100]; wreq.u.essid.pointer = id; wreq.u.essid.length = 100; if ( ioctl(sockfd,SIOCGIWESSID, &wreq) == -1 ) { continue; } else { strcpy(ESSID,id); return ESSID; } free(id); } free(line); fclose(fp); return result; }