Unable to receive data with libusb - c

I want to send and receive data from device to pc and vice versa. I am sending the string, but not able to receive it fully. Example: Sent string is Hello, and the output is:
Received:H
Error in read! e = -4 and received = 5
#include <string.h>
#include<stdio.h>
#include <stdlib.h>
#include <libusb-1.0/libusb.h>
#define BULK_EP_OUT 0x01
#define BULK_EP_IN 0x81
/*find these values using lsusb -v*/
uint16_t VENDOR = 0x0483;
uint16_t PRODUCT = 0x5740;
int main(void)
{
int ret = 1; //int type result
struct libusb_device **usb_dev;
struct libusb_device_descriptor desc;
struct libusb_device_handle *handle = NULL;
struct device_handle_expected;
//struct libusb_device_handle device_expected_handle = NULL;
struct libusb_device *dev, *dev_expected;
char *my_string, *my_string1;
int e = 0, config;
char found = 0;
int transferred = 0;
int received = 0;
int length = 0;
int i=0;
int count;
/*struct libusb_device *dev;
struct libusb_device **devs;
struct dev_expected;*/
// Initialize libusb
ret = libusb_init(NULL);
if(ret < 0)
{
printf("\nFailed to initialise libusb\n");
return 1;
}
else
printf("\nInit successful!\n");
// Get a list of USB devices
count = libusb_get_device_list(NULL, &usb_dev);
if (count < 0)
{
printf("\nThere are no USB devices on the bus\n");
return -1;
}
printf("\nToally we have %d devices\n", count);
while ((dev = usb_dev[i++]) != NULL)
{
ret = libusb_get_device_descriptor(dev, &desc);
if (ret < 0)
{
printf("Failed to get device descriptor\n");
libusb_free_device_list(dev, 1);
break;
}
e = libusb_open(dev, &handle);
if (e < 0)
{
printf("Error opening device\n");
libusb_free_device_list(dev, 1);
libusb_close(handle);
break;
}
if(desc.idVendor == 0x0483 && desc.idProduct == 0x5740)
{
found = 1;
break;
}
}//end of while
if(found == 0)
{
printf("\nDevice NOT found\n");
libusb_free_device_list(usb_dev, 1);
libusb_close(handle);
return 1;
}
else
{
printf("\nDevice found");
// dev_expected = dev;
//device_handle_expected = handle;
}
e = libusb_get_configuration(handle, &config);
if(e!=0)
{
printf("\n***Error in libusb_get_configuration\n");
libusb_free_device_list(usb_dev, 1);
libusb_close(handle);
return -1;
}
printf("\nConfigured value: %d", config);
if(config != 1)
{
libusb_set_configuration(handle, 1);
if(e!=0)
{
printf("Error in libusb_set_configuration\n");
libusb_free_device_list(usb_dev, 1);
libusb_close(handle);
return -1;
}
else
printf("\nDevice is in configured state!");
}
if(libusb_kernel_driver_active(handle, 0) == 1)
{
printf("\nKernel Driver Active");
if(libusb_detach_kernel_driver(handle, 0) == 0)
printf("\nKernel Driver Detached!");
else
{
printf("\nCouldn't detach kernel driver!\n");
libusb_free_device_list(usb_dev, 1);
libusb_close(handle);
return -1;
}
}
e = libusb_claim_interface(handle, 0);
if(e < 0)
{
printf("\nCannot Claim Interface");
libusb_free_device_list(usb_dev, 1);
libusb_close(handle);
return -1;
}
else
printf("\nClaimed Interface\n");
int nbytes = 64;
my_string = (char *) malloc(nbytes + 1);
my_string1 = (char *) malloc(nbytes + 1);
memset(my_string, '\0', 64);//The C library function void (an unsigned char) to the first n characters of the string pointed to, by the argument str.
memset(my_string1, '\0', 64);
strcpy(my_string, "Hello");
length = strlen(my_string);
printf("\nTo be sent: %s", my_string);
e = libusb_bulk_transfer(handle, BULK_EP_OUT, my_string, length, &transferred, 0);
if(e == 0 && transferred == length)
{
printf("\nWrite successful!");
printf("\nSent %d bytes with string: %s\n", transferred, my_string);
}
else
printf("\nError in write! e = %d and transferred = %d\n", e, transferred);
// sleep(3);
i = 0;
for(i = 0; i <= length; i++)
{
e = libusb_bulk_transfer(handle, BULK_EP_IN, my_string1,length, &received, 0); //64: Max Packet Length
if(e == 0 && received == length)
{
printf("\nReceived:");
printf("%c", my_string1[i]);
sleep(5);
}
else
{
printf("\nError in read! e = %d and received = %d bytes\n", e, received);
return -1;
}
}
libusb_release_interface(handle, 0);
libusb_free_device_list(usb_dev, 1);
libusb_close(handle);
libusb_exit(NULL);
printf("\n");
return 0;
}

Pretty certain the bulk in transfer will transfer the entire buffer at once(up to 64--or 512 if you're doing high speed--bytes), not a byte at a time.
You're iterating over the size of the expected buffer and doing a bulk in for each byte, and only printing out the first byte.
Get rid of the for loop on the read and change your printf() to be printf("%s\n",my_string1);

Related

Why doesn't my epoll based program improve performance by increasing the number of connections?

I have a program which reads a file of domain names (one domain per line) and performs asynchronous DNS resolution and then downloads the landing page for each domain. The network communication is performed with an epoll based event loop. Testing has shown that increasing the number of concurrent connections does not increase performance in terms of Mbits/s throughput and in terms of number of pages downloaded. The results of my test are as follows. The first test is for 1024 concurrent connections, the second test for 2048, the third for 4096 and the fourth for 8192:
:~$ ./crawler com.lowercase
iterations=156965 total domains=5575 elapsed=65.51s domains/s=85.10 KB=28163 Mbit/s=2.86
:~$ ./crawler com.lowercase
iterations=88339 total domains=10525 elapsed=64.98s domains/s=161.98 KB=52936 Mbit/s=5.41
:~$ ./crawler com.lowercase
iterations=143989 total domains=9409 elapsed=64.80s domains/s=145.20 KB=48166 Mbit/s=4.94
:~$ ./crawler com.lowercase
iterations=109597 total domains=10532 elapsed=65.13s domains/s=161.71 KB=51874 Mbit/s=5.29
As you can see there is really no trend of increase in terms of domains downloaded per second or Mbits/s throughput. These results run contrary to expectations. Can anyone explain these results? Suggest a fix to improve performance with increasing number of connections?
For those interested a full code listing is provided below:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <time.h>
#include <ares.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#define MAXWAITING 1000 /* Max. number of parallel DNS queries */
#define MAXTRIES 3 /* Max. number of tries per domain */
#define DNSTIMEOUT 3000 /* Max. number of ms for first try */
#define DNS_MAX_EVENTS 10000
#define DNS_MAX_SERVERS 2
#define SERVERS "1.0.0.1,8.8.8.8" /* DNS server to use (Cloudflare & Google) */
#define MAXDOMAINS 8192
#define PORT 80
#define MAXBUF 1024
#define MAX_EPOLL_EVENTS 8192
#define MAX_CONNECTIONS 8192
#define TIMEOUT 10000
ares_socket_t dns_client_fds[ARES_GETSOCK_MAXNUM] = {0};
struct epoll_event ev, dns_events[DNS_MAX_EVENTS];
int i,bitmask,nfds, epollfd, timeout, fd_count, ret;
int epfd;
int sockfd[MAX_CONNECTIONS];
struct epoll_event event[MAX_CONNECTIONS];
struct sockaddr_in dest[MAX_CONNECTIONS];
char resolved[MAXDOMAINS][254];
char ips[MAXDOMAINS][128];
int current = 0, active = 0, next = 0;
char servers[MAX_CONNECTIONS][128];
char domains[MAX_CONNECTIONS][254];
char get_buffer[MAX_CONNECTIONS][1024];
char buffer[MAX_CONNECTIONS][MAXBUF];
int buffer_used[MAX_CONNECTIONS];
struct timespec startTime, stopTime;
int i, num_ready, connections = 0, done = 0, total_bytes = 0, total_domains = 0, iterations = 0, count = 0;
FILE * fp;
struct epoll_event events[MAX_EPOLL_EVENTS];
static int nwaiting;
static void state_cb(void *data, int s, int read, int write)
{
//printf("Change state fd %d read:%d write:%d\n", s, read, write);
}
static void callback(void *arg, int status, int timeouts, struct hostent *host)
{
nwaiting--;
if(!host || status != ARES_SUCCESS){
//fprintf(stderr, "Failed to lookup %s\n", ares_strerror(status));
return;
}
char ip[INET6_ADDRSTRLEN];
if (host->h_addr_list[0] != NULL){
inet_ntop(host->h_addrtype, host->h_addr_list[0], ip, sizeof(ip));
strcpy(resolved[current], host->h_name);
strcpy(ips[current], ip);
if (current < MAXDOMAINS - 1) current++; else current = 0;
active++;
printf("active %d\r", active);
}
}
static void wait_ares(ares_channel channel)
{
nfds=0;
bitmask=0;
for (i =0; i < DNS_MAX_SERVERS ; i++) {
if (dns_client_fds[i] > 0) {
if (epoll_ctl(epollfd, EPOLL_CTL_DEL, dns_client_fds[i], NULL) < 0) {
continue;
}
}
}
memset(dns_client_fds, 0, sizeof(dns_client_fds));
bitmask = ares_getsock(channel, dns_client_fds, DNS_MAX_SERVERS);
for (i =0; i < DNS_MAX_SERVERS ; i++) {
if (dns_client_fds[i] > 0) {
ev.events = 0;
if (ARES_GETSOCK_READABLE(bitmask, i)) {
ev.events |= EPOLLIN;
}
if (ARES_GETSOCK_WRITABLE(bitmask, i)) {
ev.events |= EPOLLOUT;
}
ev.data.fd = dns_client_fds[i];
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, dns_client_fds[i], &ev) < 0) {
if(errno == EEXIST) {
nfds++;
continue;
}
continue;
}
nfds++;
}
}
if(nfds==0)
{
return;
}
timeout = 1000;//millisecs
fd_count = epoll_wait(epollfd, dns_events, DNS_MAX_EVENTS, timeout);
if (fd_count < 0) {
return;
}
if (fd_count > 0) {
for (i = 0; i < fd_count; ++i) {
ares_process_fd(channel, ((dns_events[i].events) & (EPOLLIN) ? dns_events[i].data.fd:ARES_SOCKET_BAD), ((dns_events[i].events) & (EPOLLOUT)? dns_events[i].data.fd:ARES_SOCKET_BAD));
}
} else {
ares_process_fd(channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
}
}
void make_socket_and_connect (int sock)
{
if ( (sockfd[sock] = socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK, 0)) < 0 ) {
perror("Socket");
exit(errno);
}
count++;
event[sock].events = EPOLLIN|EPOLLOUT;
event[sock].data.fd = sockfd[sock];
epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd[sock], &event[sock]);
bzero(&dest[sock], sizeof(dest[sock]));
dest[sock].sin_family = AF_INET;
dest[sock].sin_port = htons(PORT);
if ( inet_pton(AF_INET, servers[sock], &dest[sock].sin_addr.s_addr) == 0 ) {
printf("\n");
perror(servers[sock]);
exit(errno);
}
if ( connect(sockfd[sock], (struct sockaddr*)&dest[sock], sizeof(dest[sock])) != 0 ) {
if(errno != EINPROGRESS) {
printf("%s\n", servers[sock]);
perror("Connect again ");
//exit(errno);
}
buffer_used[sock] = 0;
}
}
int is_valid_ip(char *domain)
{
if (!strcmp(domain, "255.255.255.255"))
return 0;
if (!strcmp(domain, "192.168.1.0"))
return 0;
if (!strcmp(domain, "127.0.0.0"))
return 0;
return 1;
}
void close_socket (int socket)
{
close(sockfd[socket]);
count--;
epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd[socket], &event[socket]);
}
void get_domain_and_ip(int id)
{
//close_socket(id);
active--;
get_domain_name:
strcpy(servers[id], ips[next]);
strcpy(domains[id], resolved[next]);
if (next < (MAXDOMAINS - 1)) next++; else next = 0;
if (is_valid_ip(servers[id]))
{
make_socket_and_connect(id);
total_domains++;
}
else
goto get_domain_name;
}
void get_domain_and_ip_without_connect(int id)
{
get_domain_name2:
strcpy(servers[id], ips[next]);
strcpy(domains[id], resolved[next]);
if (next < (MAXDOMAINS - 1)) next++; else next = 0;
if (!is_valid_ip(servers[id]))
goto get_domain_name2;
}
void get_time()
{
clock_gettime(CLOCK_MONOTONIC, &stopTime);
uint64_t msElapsed = (stopTime.tv_nsec - startTime.tv_nsec) / 1000000 + (stopTime.tv_sec - startTime.tv_sec) * 1000;
double seconds = (double)msElapsed / 1000.0;
iterations++;
fprintf(stderr, "iterations=%d total domains=%d elapsed=%2.2fs domains/s=%2.2f KB=%d Mbit/s=%2.2f num_ready=%d count=%d active=%d next=%d current=%d.....\r"
, iterations, total_domains, seconds, total_domains/seconds, total_bytes/1024, 8*total_bytes/seconds/1024/1204, num_ready, count, active, next, current);
}
ssize_t send_data(int id)
{
ssize_t nByte = send(sockfd[id], get_buffer[id] + buffer_used[id], strlen(get_buffer[id]) - buffer_used[id], 0);
return nByte;
}
ssize_t recv_data(int id)
{
ssize_t nByte = recv(sockfd[id], buffer[id], sizeof(buffer[id]), 0);
return nByte;
}
int wait()
{
int ret = epoll_wait(epfd, events, MAX_EPOLL_EVENTS, TIMEOUT/*timeout*/);
return ret;
}
int main(int argc, char *argv[]) {
sigaction(SIGPIPE, &(struct sigaction){SIG_IGN}, NULL);
FILE * fp;
char domain[254];
size_t len = 0;
ssize_t read;
ares_channel channel;
int status, dns_done = 0;
int optmask;
status = ares_library_init(ARES_LIB_INIT_ALL);
if (status != ARES_SUCCESS) {
printf("ares_library_init: %s\n", ares_strerror(status));
return 1;
}
struct ares_options options = {
.timeout = DNSTIMEOUT, /* set first query timeout */
.tries = MAXTRIES /* set max. number of tries */
};
optmask = ARES_OPT_TIMEOUTMS | ARES_OPT_TRIES;
status = ares_init_options(&channel, &options, optmask);
if (status != ARES_SUCCESS) {
printf("ares_init_options: %s\n", ares_strerror(status));
return 1;
}
status = ares_set_servers_csv(channel, SERVERS);
if (status != ARES_SUCCESS) {
printf("ares_set_servers_csv: %s\n", ares_strerror(status));
return 1;
}
memset(dns_client_fds, 0, sizeof(dns_client_fds));
memset((char *)&ev, 0, sizeof(struct epoll_event));
memset((char *)&dns_events[0], 0, sizeof(dns_events));
epollfd = epoll_create(DNS_MAX_SERVERS);
fp = fopen(argv[1], "r");
if (!fp)
exit(EXIT_FAILURE);
do{
if (nwaiting >= MAXWAITING || dns_done) {
do {
wait_ares(channel);
} while (nwaiting > MAXWAITING);
}
if (!dns_done) {
if (fscanf(fp, "%253s", domain) == 1) {
ares_gethostbyname(channel, domain, AF_INET, callback, NULL);
nwaiting++;
} else {
//fprintf(stderr, "done sending\n");
dns_done = 1;
}
}
} while (active < MAX_CONNECTIONS);
/*---Open sockets for streaming---*/
for (i = 0; i < MAX_CONNECTIONS; i++)
{
if ( (sockfd[i] = socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK, 0)) < 0 ) {
perror("Socket");
exit(errno);
}
count++;
}
/*---Add sockets to epoll---*/
epfd = epoll_create1(0);
for (i = 0; i < MAX_CONNECTIONS; i++)
{
event[i].events = EPOLLIN|EPOLLOUT;
event[i].data.fd = sockfd[i];
epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd[i], &event[i]);
}
/*---Initialize server address/port structs---*/
for (i = 0; i < MAX_CONNECTIONS; i++)
{
get_domain_and_ip_without_connect(i);
//printf("%s %s\n", servers[i], domains[i]);
bzero(&dest[i], sizeof(dest[i]));
dest[i].sin_family = AF_INET;
dest[i].sin_port = htons(PORT);
if ( inet_pton(AF_INET, servers[i], &dest[i].sin_addr.s_addr) == 0 ) {
perror(servers[i]);
exit(errno);
}
}
/*---Connect to servers---*/
for (i = 0; i < MAX_CONNECTIONS; i++)
{
if ( connect(sockfd[i], (struct sockaddr*)&dest[i], sizeof(dest[i])) != 0 ) {
if(errno != EINPROGRESS) {
perror("Connect ");
//exit(errno);
}
buffer_used[i] = 0;
}
}
clock_gettime(CLOCK_MONOTONIC, &startTime);
while (1)
{
/*---Do async DNS---*/
while (active < MAXDOMAINS && nwaiting > 0) {
//printf("active = %d MAXDOMAINS = %d nwaiting = %d MAXWAITING = %d\n", active, MAXDOMAINS, nwaiting, MAXWAITING);
if (nwaiting >= MAXWAITING || dns_done) {
do {
wait_ares(channel);
} while (nwaiting > MAXWAITING);
}
if (!dns_done) {
if (fscanf(fp, "%253s", domain) == 1) {
ares_gethostbyname(channel, domain, AF_INET, callback, NULL);
nwaiting++;
} else {
//fprintf(stderr, "done sending\n");
dns_done = 1;
}
}
} //while (active < MAXDOMAINS);
/*---Wait to be able to send---*/
num_ready = wait();
get_time();
if (!num_ready) break;
for(i = 0; i < num_ready; i++) {
int index;
if(events[i].events & EPOLLOUT) {
for (int j = 0; j < MAX_CONNECTIONS; j++)
{
if (events[i].data.fd == sockfd[j])
{
index = j;
break;
}
}
snprintf(get_buffer[index], sizeof(get_buffer[index]),
"GET %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36\r\n\r\n", "/", domains[i]);
ssize_t nByte = 0;
if (buffer_used[index] < strlen(get_buffer[index]))
nByte = send_data(index);
if (nByte > 0)
{
buffer_used[index] += nByte;
total_bytes += nByte;
}
if (nByte == -1 && errno == EPIPE)
{
get_domain_and_ip(index);
}
}
if(events[i].events & EPOLLIN) {
for (int j = 0; j < MAX_CONNECTIONS; j++)
{
if (events[i].data.fd == sockfd[j])
{
index = j;
break;
}
}
bzero(buffer[index], MAXBUF);
ssize_t nByte = recv_data(index);
//if (nByte > 0) printf("Received: %s from %s at %s \n", buffer[index], domains[index], servers[index]);
if (nByte > 0) total_bytes += nByte;
if (nByte == 0)
{
close_socket(index);
if (!done)
{
get_domain_and_ip(index);
}
}
}
}
get_time();
if (done && count == 0) break;
}
ares_destroy(channel);
ares_library_cleanup();
fclose(fp);
printf("\nFinished without errors\n");
return 0;
}
EDIT
As requested I've performed more extensive testing with smaller numbers of concurrent connections. The results are below. The results are for 2, 4, 8, 16, 32, 64, 128, 256 and 512 concurrent connections.
total domains=4 elapsed=60.37s domains/s=0.07 KB=5 Mbit/s=0.00
total domains=0 elapsed=60.39s domains/s=0.00 KB=5 Mbit/s=0.00
total domains=17 elapsed=60.40s domains/s=0.28 KB=73 Mbit/s=0.01
total domains=17 elapsed=60.48s domains/s=0.28 KB=106 Mbit/s=0.01
total domains=40 elapsed=60.45s domains/s=0.66 KB=189 Mbit/s=0.02
total domains=172 elapsed=60.37s domains/s=2.85 KB=907 Mbit/s=0.10
total domains=312 elapsed=60.56s domains/s=5.15 KB=1272 Mbit/s=0.14
total domains=1165 elapsed=60.65s domains/s=19.21 KB=5687 Mbit/s=0.62
total domains=1966 elapsed=60.34s domains/s=32.58 KB=9884 Mbit/s=1.09
The tests show that for smaller numbers of concurrent connections we do see an increase in performance for increasing numbers of concurrent connections.
EDIT
As requested in chat here is a link to the file of domains I am testing with. Warning - the file is over 2GB in size. It has over 130M domains. domains Or if you just want 100,000 here is another link to play with 100,000 domains

why \n stop the next send socket? C

I've tried to put \0 at the end of the message, but that didn't work. I've also put the terminating char when receiving the socket in the client side but that didn't work either. Here is an image of the console:
server side:
char u[BUFFER]
char *msg = "You are required to enter username:\n\n";
send(clie, msg, strlen(msg), 0);
// not shown on console
char *u_msg = "Username: ";
send(clie, u_msg, strlen(u_msg), 0);
recv(clie, u, sizeof(u), 0);
client-side
char srecv[BUFFER]; // BUFFER = 1024
while (1) {
bytes = recv(ser, & srecv, BUFFER, 0);
srecv[bytes] = '\0';
printf("%s", srecv);
scanf("%s", ssend);
if (send(ser, ssend, strlen(ssend), 0) == -1) {
perror("send\n");
exit(1);
}
}
Since there are multiple '\n' characters in your server's messaging, that is not sufficient to let the client know when each message has finished being received. You should either:
send a message's length before sending the actual message.
send a unique terminator at the end of each message (in your example, the null terminator will suffice).
Either way will allow the client to keep reading and displaying a message's bytes to the console until the true end of message has been reached, BEFORE then reading the user's response from the console. The client MUST wait to receive both messages in their entirety before then calling scanf().
There is no 1:1 relationship between send() and recv() in TCP, you MUST be prepared to handle that. Both functions MAY return fewer bytes than requested, so both functions must be called in loops until all expected bytes are sent/received. And messages MUST be explicitly framed by the sender in such a way that the receiver knows when a message actually ends.
Try something more like this instead:
Common code for both sides:
int sendAll(int sckt, const void *data, size_t size)
{
const char *pdata = (const char*) data;
while (size > 0)
{
ssize_t sent = send(sckt, pdata, size, 0);
if (sent < 0) return -1;
pdata += sent;
size -= sent;
}
return 0;
}
int recvAll(int sckt, void *data, size_t size)
{
char *pdata = (char*) data;
while (size > 0)
{
ssize_t recvd = recv(sckt, pdata, size, 0);
if (recvd <= 0) return recvd;
pdata += recvd;
size -= recvd;
}
return 1;
}
int sendMsg(int sckt, const char *msg)
{
uint32_t msglen = strlen(msg);
uint32_t temp = htonl(msglen);
int ret = sendAll(sckt, &temp, sizeof(temp));
if (ret == 0) ret = sendAll(sckt, msg, msglen);
return ret;
}
int recvMsg(int sckt, char **msg)
{
*msg = NULL;
uint32_t msglen = 0;
int ret = recvAll(sckt, &msglen, sizeof(msglen));
if (ret <= 0) return ret;
msglen = ntohl(msglen);
char *pmsg = (char*) malloc(msglen+1);
if (!pmsg) return NULL;
if (msglen > 0)
{
ret = recvAll(sckt, pmsg, msglen);
if (ret <= 0)
{
free(pmsg);
return ret;
}
}
pmsg[msglen] = '\0';
*msg = pmsg;
return 1;
}
Alternatively:
int sendMsg(int sckt, const char *msg)
{
if (!msg) msg = "\0";
int size = strlen(msg) + 1;
do
{
ssize_t sent = send(sckt, msg, size, 0);
if (sent < 0) return -1;
msg += sent;
size -= sent;
}
while (size > 0);
return 0;
}
int recvMsg(int sckt, char **msg)
{
char c, buf[1024];
int inbuf = 0;
char *pmsg = NULL;
int msglen = 0;
*msg = NULL;
do
{
ssize_t ret = recv(sckt, &c, 1, 0);
if (ret <= 0)
{
if (pmsg) free(pmsg);
return ret;
}
if (c == '\0')
break;
if (inbuf == sizeof(buf))
{
char *newmsg = (char*) realloc(msg, msglen + inbuf + 1);
if (!newmsg)
{
if (pmsg) free(pmsg);
return -1;
}
memcpy(buf, &newmsg[msglen], inbuf);
newmsg[msglen + inbuf] = '\0';
pmsg = newmsg;
msglen += inbuf;
inbuf = 0;
}
buf[inbuf] = c;
++inbuf;
}
while (1);
if ((inbuf > 0) || (msglen == 0))
{
char *newmsg = (char*) realloc(msg, msglen + inbuf + 1);
if (!newmsg)
{
if (pmsg) free(pmsg);
return -1;
}
if (inbuf > 0) memcpy(buf, &newmsg[msglen], inbuf);
newmsg[msglen + inbuf] = '\0';
pmsg = newmsg;
}
*msg = pmsg;
return 1;
}
Server side:
sendMsg(clie, "You are required to enter username:\n\n");
sendMsg(clie, "Username: ");
char *u;
if (recvMsg(clie, &u) == 1)
{
...
free(u);
}
Client side:
char *msg;
while (1) {
ret = recvMsg(ser, &msg);
if (ret <= 0)
{
if (ret < 0)
{
perror("recvMsg\n");
exit(1);
}
break;
}
printf("%s", msg);
if (strcmp(msg, "Username: ") == 0)
{
scanf("%s", ssend);
if (sendMsg(ser, ssend) == -1)
{
perror("sendMsg\n");
exit(1);
}
}
free(msg);
}

C TCP sockets: read () on socket returns Resourse temporarily unavailable

The system I realize consists of a ring of tokens (each token is a ckient-server process).
I tested it runnimy two processes.
In function serverMessageProcessor() I call readMessage() function, in which I use read() to read all parts of a message from an (in)socket and (after processes it) write another message on (out)socket.
The first time I do it, it works well, the second time, one of the read() function in my readMessage() function, gives read: Success (I use perror to catch read error) and read: Resourse temporarily unavailable on the other process.
There are some prints for debugging in the code.
I hope you can help me.
Thanks a lot in advance.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h> //per le funzioni sui socket.
#include <arpa/inet.h> //per la funzione inet_aton().
#include <netinet/in.h> //per la struct sockaddr.
#include <sys/wait.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <ctype.h> //per la funzione isdigit().
#include <fcntl.h> //per rendere il socket bloccante o no.
#include <sys/select.h>
/* Error hendler */
void sys_error (const char *message) {
perror (message);
}
/* Connessione in ingresso */
int setUpConnectionIn(int port, int *sock_fd){
int sock_in;
struct sockaddr_in addr;
addr.sin_family = AF_INET; //Internet Address Family.
addr.sin_port=htons(port); //Local port.
addr.sin_addr.s_addr = htonl(INADDR_ANY); //Any incoming interface.
//Create socket for incoming connections.
if((sock_in = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
stampaStr("Errore: Creazione socket non riuscita.", 1);
return -1;
}
//Bind to the local address.
if(bind(sock_in, (struct sockaddr *) &addr, sizeof(addr)) < 0){
sys_error("Errore: impossibile assegnare l'indirizzo al socket.");
close(sock_in);
return -1;
}
//Mark the socket so it will listen for incoming connections.
if(listen(sock_in,5) < 0) {
sys_error("Errore: listen non riuscita.");
close(sock_in);
return -1;
}
*sock_fd = sock_in;
return 0;
}
/* Interfaccia Connessione in ingresso */
int setUpConnectionIn_2 (int sock_fd){
int connection_in;
if ((connection_in = accept(sock_fd, NULL, NULL)) < 0) {
sys_error ("Errore in funzione setUpConnectionIn_2");
return -1;
}
return connection_in;
}
/* Connessione in uscita */
int setUpConnectionOut (int *sock_fd, int connection_port, char *conn_addr){
int check;
struct sockaddr_in addr_out;
int sock_out;
addr_out.sin_family = AF_INET;
addr_out.sin_port = htons(connection_port);
if (inet_aton(conn_addr, &addr_out.sin_addr) < 0) {
sys_error ("Errore: inet_aton");
return -1;
}
if((sock_out = socket(PF_INET, SOCK_STREAM, 0))<0) {
sys_error("Errore: Creazione socket non riuscita.");
return -1;
}
stampaStr("In attesa di connessione alla stazione successiva..\n", 1);
while(connect(sock_out, (struct sockaddr *)&addr_out, sizeof(addr_out)) < 0);
*sock_fd = sock_out;
return 0;
}
int closed_ring = 0;
int readMessage (int *fd, unsigned char *cod, int *size, char **content) {
char *content_msg;
unsigned char cod_msg;
int size_msg;
int retval = fcntl(*fd, F_SETFL, fcntl(*fd, F_GETFL) | O_NONBLOCK);
printf ("readMessage - prima read\n");
if (read(*fd, &cod_msg, 1) == 0) {
sys_error ("read - cod_msg");
return -1;
}
if (read(*fd, &size_msg, 4) == 0) {
sys_error ("read - size_msg");
return -1;
}
*content = (char *)malloc((size_msg+1)*sizeof(char));
(*content)[size_msg+1] = '\0';
if (read(*fd, *content, size_msg) == 0) {
sys_error ("read - content_msg");
return -1;
}
retval = fcntl(*fd, F_SETFL, (fcntl(*fd, F_GETFL) | O_NONBLOCK) & (~O_NONBLOCK));
printf ("readMessage - dopo read\n");
printf ("(readMessage)cod: %c - size: %d - msg: %s\n", cod_msg, size_msg, *content);
*cod = cod_msg;
*size = size_msg;
//content = (char *)malloc(size_msg*sizeof(char));
//memcpy(content, content_msg, strlen(content_msg));
//content = content_msg;
printf ("content: %s\n", *content);
return 0;
}
int buildMessage (char **new_msg, unsigned char cod, int size, char *content) {
int msg_len = size+6;
*new_msg = (char *)malloc(msg_len*sizeof(char));
(*new_msg)[0] = cod;
memcpy (((*new_msg)+1), &size, 4);
memcpy (((*new_msg)+5), content, size);
(*new_msg)[msg_len] = '\0';
//new_msg = msg;
return strlen (*new_msg);
}
int serverMessageProcessor (int *fd_in, int *out_fds) {
char *new_msg;
char *content_msg;
unsigned char cod_msg = 100;
int size_msg;
int msg_length;
char *tmp_PID_str;
uint64_t myPID;
uint64_t tempPID;
int fd;
if (readMessage (fd_in, &cod_msg, &size_msg, &content_msg) < 0) {
sys_error ("readMessage");
return -1;
}
printf ("(serverMessageProcessor) cod: %c - size: %d - msg: %s\n", cod_msg, size_msg, content_msg);
printf ("serverMessageProcessor - prima switch\n");
switch (cod_msg) {
case ('1'): {
fd = 0;
if ((myPID = getpid()) < 0) {
sys_error ("getpid");
return -1;
}
tmp_PID_str = (char *)malloc((size_msg+1)*sizeof(char));
tmp_PID_str[size_msg+1] = '\0';
printf ("serverMessageProcessor - prima memcpy(myPID) PID: %ld\n", myPID);
memcpy (tmp_PID_str, &myPID, sizeof(uint64_t));
printf ("serverMessageProcessor - dopo memcpy(myPID)\n");
if (strcmp (content_msg, tmp_PID_str) == 0) {
printf ("serverMessageProcessor - dopo strcmp TRUE (myPID, tempPID)\n");
closed_ring = 1;
} else {
//new_msg = (char *)malloc(size_msg+6)*sizeof(char));
printf ("serverMessageProcessor - dopo strcmp FALSE (myPID, tempPID)\n");
//msg_length = buildMessage (&new_msg, cod_msg, size_msg, content_msg);
msg_length = size_msg+6;
new_msg = (char *)malloc(msg_length*sizeof(char));
new_msg[0] = cod_msg;
memcpy (new_msg+1, &size_msg, 4);
memcpy (new_msg+5, content_msg, size_msg);
new_msg[msg_length] = '\0';
printf ("serverMessageProcessor - dopo buildMessage: %s\n", new_msg);
printf ("(serverMessageProcessor) cod: %c - size: %d - msg: %s\n", cod_msg, size_msg, content_msg);
if (write (out_fds[fd], &cod_msg, 1) < 0) {
sys_error ("write");
return -1;
}
if (write (out_fds[fd], &size_msg, 4) < 0) {
sys_error ("write");
return -1;
}
if (write (out_fds[fd], content_msg, size_msg) < 0) {
sys_error ("write");
return -1;
}
printf ("serverMessageProcessor - dopo write\n");
}
printf ("serverMessageProcessor - fuori if strcmp(myPID, tempPID)\n");
}
}
}
int main (int argc, char *argv[]) {
int listen_port, connection_port;
int connection;
int check = -1;
char *conn_addr;
char inter_lv = 'a';
int sock_in; //socket descriptor for reading.
int sock_out; //socket descriptor for writing.
struct sockaddr_in addr_in;
struct sockaddr_in addr_out;
int connection_flag = 0;
int out_fds[3];
/********************* VARIABILI GESTIONE MESSAGGI ************************/
char *new_msg = NULL;
char *content_msg = NULL;
unsigned char cod_msg;
int size_msg;
int msg_len;
uint64_t tempPID;
uint64_t myPID;
/**************************************************************************/
/********************** VARIABILI GESTIONE SOTTOPROCESSI ******************/
int pipe_IN[2];
int pipe_OUT[2];
int pipe_CLIENT[2];
int pid_client;
/**************************************************************************/
/***************************** VARIABILI PER SELECT SYSCALL ***************/
fd_set rfds;
struct timeval tv;
int retval;
/**************************************************************************/
if(readIntFromString(0, &listen_port, argv[1]) < 0){
printf("Invalid value of listen_port\n");
return -1;
}
if(listen_port >= 0 && listen_port <= 1023){
printf("Insert a port in range 0-1023\n");
return -1;
}
if(listen_port >= 49152){
printf("Insert a port not higher than 49152\n");
return -1;
}
if(readIntFromString(0, &connection_port, argv[2]) < 0){
printf("Invalid value of connection_port\n");
return -1;
}
if(connection_port >= 0 && connection_port <= 1023){
printf("Insert a port in range 0-1023\n");
return -1;
}
if(connection_port >= 49152){
printf("Insert a port not higher than 49152\n");
return -1;
}
conn_addr = argv[3];
if((toupper(argv[4][0]) == 'S' || toupper(argv[4][0]) == 'N') && argv[4][1] == '\0'){
inter_lv = toupper(argv[4][0]);
}else{
printf("Invalid Interactivity Level\n");
return -1;
}
/*********************** Circuit Building **************************/
if(setUpConnectionIn(listen_port, &sock_in) < 0) {
sys_error ("Errore in funzione: setUpConnectionIn");
return -1;
}
if (setUpConnectionOut (&sock_out, connection_port, conn_addr) < 0) {
sys_error ("Errore in funzione setUpConnectionOut");
return -1;
}
printf ("-------------out-connected-------------\n");
if ((connection = setUpConnectionIn_2 (sock_in)) < 0) {
sys_error ("Errore in funzione setUpConnectionIn_2");
return -1;
}
printf ("-------------in-connected--------------\n");
/**********************************************************************/
/* Controlla connection (socket in entrata) per vedere se è pronto per operazioni di I/O */
//retval = fcntl(connection, F_SETFL, fcntl(connection, F_GETFL) | O_NONBLOCK);
FD_ZERO(&rfds);
FD_SET(connection, &rfds);
out_fds[0] = sock_out;
/* Attende 5 secondi */
tv.tv_sec = 5;
tv.tv_usec = 0;
while (closed_ring == 0) {
if (connection_flag == 0) {
if ((myPID = getpid()) < 0) {
sys_error ("getpid");
return -1;
}
size_msg = sizeof(uint64_t);
msg_len = size_msg+6;
new_msg = (char*)malloc(msg_len*sizeof(char));
new_msg[0] = '1';
memcpy(new_msg+1, &size_msg, 4);
memcpy(new_msg+5, &myPID, size_msg);
new_msg[msg_len] = '\0';
printf ("(MAIN) myPID: %ld - cod: %c - size: %d - msg: %s\n", myPID, new_msg[0], size_msg, &(new_msg[5]));
if (write (out_fds[0], new_msg, msg_len) < 0) {
sys_error ("write");
return -1;
}
printf ("Message 1 (ring closing) sent: %s\n", new_msg);
connection_flag = 1;
}
retval = select(connection+1, &rfds, NULL, NULL, &tv);
if (retval == -1) {
sys_error ("select");
return -1;
} else if (retval) {
stampaStr("Available data on (in)socket\n", 1); /* FD_ISSET(0, &rfds) avrà valore TRUE */
/*************** DEBUG ************************
if (read (connection, &cod_msg, 1) == 0) {
sys_error ("read - main");
return -1;
} else {
printf ("read - main: %c\n", cod_msg);
}
**********************************************/
if (serverMessageProcessor (&connection, out_fds) < 0) {
sys_error ("serverMessageProcessor");
return -1;
}
} else {
stampaStr("None message in entry\n", 1);
char c = getchar();
fflush(stdin);
}
}
/* Creazione sottoprocesso per gestione connessioni con Client per iscrizione auto */
if (pipe(pipe_CLIENT) < 0) {
sys_error ("pipe_client");
return -1;
}
if ((pid_client = fork()) < 0) {
sys_error ("fork_client");
return -1;
} else if (pid_client == 0) { /* Processo figlio - accetta connessioni da Client */
printf("Subprocess to manage client(s) connection\n");
//while (1);
} else { /* Processo Padre */
printf("Parent process\n");
}
return 0;
}
When read() returns 0, it means the socket has been closed by the other end, it's not an error, so you shouldn't call sys_error(). An error is indicated by read() returning -1. That's why you're getting Success as the error message.
However, you've set the socket to be non-blocking, so read() will also return -1 when there's nothing available to be read. It will set errno = EAGAIN in this case, and the message for this is Resource temporarily Available.
You need to test for this and go back to your loop that waits for data with select(). This is normal for non-blocking sockets, so you shouldn't report it as an error.
So the code should be like:
if (read(*fd, &cod_msg, 1) == -1) {
if (errno == EAGAIN) {
return -2;
} else {
sys_error ("read - cod_msg");
return -1;
}
}
I've changed this to return -2 in the EAGAIN case, you'll need to change the caller to check for this so it doesn't call sys_error either.

In c socket, why my server can't receive the whole content?

I am new in this field, and writing one server and client, but it really confusing that I can't get all the content, but some small clip.
My server code:
read(connfd, name, 20);
//recv(connfd,name,1024,0);
char* a=name;
while(a[0]!='\n'){
a++;
}
a[0]='\0';
printf("name:%s\n", name);
read(connfd, size, 20);
printf("size:%s\n", size);
recv(connfd,buf,8192,0);
printf("buf:%s\n", buf);
if((stream = fopen(name,"w+t"))==NULL){
printf("The file was not opened! \n");
}
int write_length = fwrite(buf,sizeof(char),8192,stream);
bzero(buf,8192);
if(put){
char *res="OK\n";
write(connfd, res, 1024);
}
fclose(stream);
and my client code is:
char buffer[8192];
bzero(buffer,8192);
char * put="PUT\n";
if ((write(fd, put, 8192)) <= 0) {
if (errno != EINTR) {
fprintf(stderr, "Write error: %s\n", strerror(errno));
exit(0);
}
}
struct stat st ;
stat( put_name, &st );
char str[100];
sprintf(str, "%d", st.st_size);
int len;
char *current=NULL;
len=strlen(put_name);
char sendname[1024];
strcpy(sendname,put_name);
strcat(sendname,"\n");
write(fd, sendname, 10);
strcat(str,"\n");
write(fd, str, 10);
FILE *stream;
if((stream = fopen(put_name,"r"))==NULL)
{
printf("The file was not opened! \n");
exit(1);
}
int lengsize = 0;
while((lengsize = fread(buffer,1,8192,stream)) > 0){
if(send(fd,buffer,8192,0)<0){
printf("Send File is Failed\n");
break;
}
bzero(buffer, 8192);
}
Now, I can send all content, but can receive part of them. for example, on my mac, server can receive name but the str is neglected, when I printf the str in the server, it shows the content of file. and the content of file is not the whole file content. Some content disappear. Could you tell me why?
The read and write functions are not guaranteed to send or receive the entire message with a single call. Instead, you're expected to sit in a loop, writing the message incrementally until everything has been sent and reading everything incrementally until everything has been read. For example, if you know exactly how much has been sent, you can do this:
char recvBuffer[BUFFER_SIZE];
int bytesRead = 0;
while (bytesRead < BUFFER_SIZE) {
int readThisTime = read(file, recvBuffer + bytesRead, BUFFER_SIZE - bytesRead);
if (readThisTime == -1) {
// handle error...
}
bytesRead += readThisTime;
}
If you don't know exactly how much has been sent, try this:
char recvBuffer[BUFFER_SIZE];
int bytesRead = 0;
while (bytesRead < BUFFER_SIZE) {
int readThisTime = read(file, recvBuffer + bytesRead, BUFFER_SIZE - bytesRead);
if (readThisTime == -1) {
// handle error...
}
if (readThisTime == 0) break; // Done!
bytesRead += readThisTime;
}
You are ignoring the return values of send() and recv(). You MUST check return values!
When sending the file, lengsize receives how many bytes were actually read from the file. Your client is sending too many bytes when lengsize is < 8192 (typically the last block of the file if the file size is not an even multiple of 8192).
But more importantly, although the client is telling the server the file size, the server is ignoring it to know when to stop reading. The server is also ignoring the return value of recv() to know how many bytes were actually received so it knows how many bytes can safely be written to the output file.
Try something more like this instead:
common:
int readData(int s, void *buf, int buflen)
{
int total = 0;
char *pbuf = (char*) buf;
while (buflen > 0) {
int numread = recv(s, pbuf, buflen, 0);
if (numread <= 0) return numread;
pbuf += numread;
buflen -= numread;
total += numread;
}
return total;
}
int sendData(int s, void *buf, int buflen)
{
int total = 0;
char *pbuf = (char*) buf;
while (buflen > 0) {
int numsent = send(s, pbuf, buflen, 0);
if (numsent <= 0) return numsent;
pbuf += numsent;
buflen -= numsent;
total += numsent;
}
return total;
}
int readInt32(int s, int32_t *value)
{
int res = readData(s, value, sizeof(*value));
if (res > 0) *value = ntohl(*value);
return res;
}
int sendInt32(int s, int32_t value)
{
value = htonl(value);
return sendData(s, &value, sizeof(value));
}
char* readStr(int s)
{
int32_t size;
if (readInt32(s, &size) <= 0)
return NULL;
char *str = malloc(size+1);
if (!str)
return NULL;
if (readData(s, str, size) <= 0) {
free(str);
return NULL;
}
str[size] = '\0';
return str;
}
int sendStr(int s, const char *str)
{
int len = strlen(str);
int res = sendInt32(s, len);
if (res > 0)
res = sendData(s, str, len);
return res;
}
server:
char buffer[8192];
char *name = readStr(connfd);
if (!name) {
// error handling ...
sendStr(connfd, "Socket read error");
return;
}
printf("name:%s\n", name);
int32_t filesize;
if (readInt32(connfd, &filesize) <= 0) {
// error handling ...
free(name);
sendStr(connfd, "Socket read error");
return;
}
printf("size:%d\n", filesize);
if ((stream = fopen(name, "wb")) == NULL) {
// error handling ...
printf("The file was not opened!\n");
free(name);
sendStr(connfd, "File not opened");
return;
}
while (filesize > 0) {
int numread = readData(connfd, buf, min(filesize, sizeof(buffer)));
if (numread <= 0) {
// error handling ...
close(stream);
free(name);
sendStr(connfd, "Socket read error");
return;
}
printf("buf:%.*s\n", numread, buf);
if (fwrite(buf, 1, numread, stream) != numread) {
// error handling ...
close(stream);
free(name);
sendStr(connfd, "File write error");
return;
}
filesize -= numread;
}
fclose(stream);
free(name);
sendStr(connfd, "OK");
client:
char buffer[8192];
struct stat st;
if (stat( put_name, &st ) != 0) {
// error handling ...
exit(0);
}
if ((stream = fopen(put_name, "rb")) == NULL) {
// error handling ...
printf("The file was not opened!\n");
exit(0);
}
if (sendStr(fd, put_name) <= 0) {
// error handling ...
close(stream);
exit(0);
}
int32_t filesize = st.st_size;
if (sendInt32(fd, filesize) <= 0) {
// error handling ...
close(stream);
exit(0);
}
int lengsize;
while (filesize > 0) {
lengsize = fread(buffer, 1, min(filesize , sizeof(buffer)), stream);
if (lengsize <= 0) {
printf("Read File Failed\n");
// error handling ...
close(stream);
exit(0);
}
if (sendData(fd, buffer, lengsize) <= 0) {
printf("Send File Failed\n");
// error handling ...
close(stream);
exit(0);
}
filesize -= lengsize;
}
close(stream);
char *resp = readStr(fd);
if (!resp) {
// error handling ...
exit(0);
}
if (strcmp(resp, "OK") == 0)
printf("Send File OK\n");
else
printf("Send File Failed: %s\n", resp);
free(resp);

Receiving a malloc error when running a simple client program

I am trying to test a client program to make sure that it correctly sends and receives messages from a server. When I run the program I get this weird error from malloc. Any help would be great. I've been looking at this code for way too long. Thanks in advance.
Here is the error:
// The first test runs okay
TEST 1 :
Connected to server
-> Socket open success
-> Request sent success
-> Response received success
Testing print:
Response received: <replyLoadAvg>0.228027:0.250000:0.280273</replyLoadAvg>
LoadAvg for 1min :: 0.228027
LoadAvg for 5min :: 0.250000
LoadAvg for 15min :: 0.280273
Real response -> <replyLoadAvg>0.228027:0.250000:0.280273</replyLoadAvg>
// Then I get this error for some reason
clientc(17781) malloc: ********* error for object 0x7fd048404318: incorrect checksum for
freed object - object was probably modified after being freed.
********* set a breakpoint in malloc_error_break to debug
Abort trap: 6
here is the client code:
// prototype
char* verifyString(char*);
void printLoadAvg(char*);
int receiveResponse(int, char **);
int main(int argc, char *argv[])
{
int sockfd;
char *name;
char *port;
struct sockaddr_in * dest;
if(argc != 3)
{
printf("Not enough arguments -- Exiting program\n");
return 0;
}
name = argv[1];
port = argv[2];
char * received;
char send[256];
char testMessages[5][256] = {"<loadavg/>", "<echo>Hello World!</echo>", "<echo> </echo>", "", "<echo>Bye Bye World...<echo>"};
char expectedResponses[5][256] = {"", "<reply>Hello World!</reply>", "<reply></reply>","<error>unknown format</error>", "<error>unknown format</error>"};
int i;
srand(time(NULL));
for(i = 0; i < 5; i++)
{
printf("\nTEST %i", i+1);
printf(((rand() % 2) ? ":\n" : " :\n"));
sprintf(send, "%s", testMessages[i]);
sockfd = createSocket(name, atoi(port), &dest);
if(sockfd < 0){
printf(" xx Open socket failed\n");
}
else{
printf(" -> Socket open success\n");
if(sendRequest(sockfd, send, dest) < 0){
printf(" xx Send failed\n");
}
else{
printf(" -> Request sent success\n");
if(receiveResponse(sockfd, &received) < 0){
printf(" xx Receive failed\n");
}
else{
printf(" -> Response received success\n");
if(i!=0 && strcmp(received, expectedResponses[i]) != 0){
printf("Incorrect message\n");
printf("Expected: %s\n", expectedResponses[i]);
printf("Received: %s\n", received);
}
else if(i!=0){
printf("Test %i. passed successfully!\n", i+1);
}
else{
printf("Testing print:\n");
printResponse(received);
fprintf(stdout, "Real response -> %s\n", received);
}
}
}
}
free(received);
free(dest);
if(closeSocket(sockfd)==0){
printf(" -> Socket closed success\n");
}
else{
printf(" XX Close failed\n");
}
}
return 0;
}
int createSocket( char* hostname, int port, struct sockaddr_in** dest)
{
// fill in the socket address struct
(*dest) = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
struct hostent *hostptr;
hostptr = gethostbyname(hostname);
int socketfd;
memset((void *) (*dest), 0, (size_t)sizeof(struct sockaddr_in));
(*dest)->sin_family = (short)(AF_INET);
memcpy((void*)& (*dest)->sin_addr, (void *) hostptr->h_addr, hostptr->h_length);
(*dest)->sin_port = htons((u_short)port);
// now get the file descriptor for the socket
if((socketfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
return -1;
}
// connect to the server at the location displayed by TCPserver.c
if(connect(socketfd, (struct sockaddr*)(*dest), sizeof(struct sockaddr)) < 0) {
perror("Error: call to connect()\n");
return -1;
}
printf("Connected to server\n");
return socketfd;
}
int sendRequest(int sock, char* request, struct sockaddr_in* dest)
{
// send a request through the socket to the server.
if(write(sock, request, BUFFERSIZE) < 0)
{
return -1;
}
return 0;
}
int receiveResponse(int sock, char ** response)
{
// dynamically allocate memory to be used in this function
(*response) = malloc(sizeof(char));
// wait for a response from the server
if(read(sock, (*response), BUFFERSIZE) < 0)
{
return -1;
}
return 0;
}
int closeSocket(int sock)
{
int error = 0;
if(close(sock))
{
perror("Error: Failed to close socket\n");
error = -1;
}
return error;
}
void printResponse(char* response)
{
char* buffer = "<replyloadavg>";
int i, isLoadAvg = 0;
// verify the string is in the correct format by calling the verifty string function
// then print the string to the screen.
printf("Response received: %s\n", verifyString(response));
for(i = 0; i < 14; i++)
{
if(response[i] == buffer[i])
isLoadAvg = 0;
else
{
isLoadAvg = 1;
i = 15;
}
}
if (isLoadAvg)
{
printLoadAvg(response);
}
}
char* verifyString(char* string)
{
int i, count = 0;
// step through the array until you come to the last '>' (the end of the string)
// then insert the NULL terminator at the end of the string.
for(i = 0; i < BUFFERSIZE; i++)
{
if(string[i] == '>')
count++;
if(count == 2)
{
string[i + 1] = '\0';
i = BUFFERSIZE;
}
}
return string;
}
void printLoadAvg(char* string)
{
int i = 0, j;
// these three arrays hold the newly formated strings, the ones that are easier to read.
char s1[BUFFERSIZE], s2[BUFFERSIZE], s3[BUFFERSIZE];
// step through the string until you reach the end of the string
while(string[i] != '>')
{
i++;
}
i++;
// now insert a colon and then save the contents of the string to the appropriate s array.
for(j = 0; string[i] != ':'; j++, i++)
{
s1[j] = string[i];
}
// be sure to set the null terminator at the end.
s1[j] = '\0';
i++;
for(j = 0; string[i] != ':'; j++, i++)
{
s2[j] = string[i];
}
// be sure to set the null terminator at the end.
s2[j] = '\0';
i++;
// now move to the beginning of the end of the string array
for(j = 0; string[i] != '<'; j++, i++)
{
s3[j] = string[i];
}
// now insert one more null terminator for the final s array.
s3[j] = '\0';
// now print out the newly fomrated strings.
printf("\nLoadAvg for 1min :: %s\n", s1);
printf("LoadAvg for 5min :: %s\n", s2);
printf("LoadAvg for 15min :: %s\n", s3);
}
(*response) = malloc(sizeof(char));
// wait for a response from the server
if(read(sock, (*response), BUFFERSIZE) < 0)
What size is BUFFERSIZE. Is it bigger than 1? If so, you will overflow your buffer...

Resources