Communication between C programs across a adhoc network - c

I have the following server code
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#define HELLO_PORT 12345
#define HELLO_GROUP "255.0.0.37"
main(int argc, char *argv[])
{
struct sockaddr_in addr;
struct sockaddr_in client,server;
int s,n;
char index;
int f;
char b1[100];
int fd, cnt,i=0;;
struct ip_mreq mreq;
//char *message="Hello, World!";
char *message=NULL;
/* create what looks like an ordinary UDP socket */
if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0)
{
perror("socket");
exit(1);
}
s=socket(AF_INET,SOCK_DGRAM,0);
server.sin_family=AF_INET;
server.sin_port=2000;
server.sin_addr.s_addr=inet_addr("10.42.0.47");
bind(s,(struct sockaddr *)&server,sizeof(server));
printf("\nServer ready,waiting for client....\n");
n=sizeof(client);
/* set up destination address */
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(HELLO_GROUP);
addr.sin_port=htons(HELLO_PORT);
/* now just sendto() our destination! */
while (1)
{
recvfrom(s,b1,sizeof(b1),0,(struct sockaddr *) &client,&n);
printf("client : %s\n",b1);
//sleep(5);
index=b1[0];
f=b1[0];
//printf("b1[1] is %c\n",index);
//printf("b1[0] is %c\n",f);
f=32;
b1[0]=f;
//printf("new b1[0] is %c\n",b1[0]);
//printf("%s\n",b1);
if(index!='C')
{
if (sendto(fd,b1,sizeof(b1),0,(struct sockaddr *) &addr,sizeof(addr)) < 0)
{
perror("sendto");
exit(1);
}
//i++;
/*if(i>=4)
{
i=0;
}*/
sleep(1);
}
}
}
And the following client code which runs on a different system
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdio.h>
#include <mysql.h>
#define HELLO_PORT 12345
#define HELLO_GROUP "225.0.0.37"
#define MSGBUFSIZE 1024
main(int argc, char *argv[])
{
MYSQL mysql;
MYSQL_ROW row;
MYSQL_RES *result;
unsigned int num_fields;
unsigned int i;
mysql_init(&mysql);
struct sockaddr_in server;
int s,n;
char b1[100],b2[100],a[100];
char re[100]={0};
char g=" ";
printf("%c\n",re);
strcpy(b2,"1");
char message[20],ch='n';
struct sockaddr_in addr;
int fd, nbytes,addrlen,j=0;
struct ip_mreq mreq;
char msgbuf[MSGBUFSIZE];
u_int yes=1; /*** MODIFICATION TO ORIGINAL */
/* create what looks like an ordinary UDP socket */
if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0)
{
perror("socket");
exit(1);
}
s=socket(AF_INET,SOCK_DGRAM,0);
server.sin_family=AF_INET;
server.sin_port=2000;
server.sin_addr.s_addr=inet_addr("10.42.0.1");
printf("\nClient ready....\n");
n=sizeof(server);
if (!mysql_real_connect(&mysql,"localhost","root","nidhi","project",0,NULL,0))
{
fprintf(stderr, "Failed to connect to database: Error: %s\n",
mysql_error(&mysql));
}
/**** MODIFICATION TO ORIGINAL */
/* allow multiple sockets to use the same PORT number */
if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0)
{
perror("Reusing ADDR failed");
exit(1);
}
/*** END OF MODIFICATION TO ORIGINAL */
/* set up destination address */
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY); /* N.B.: differs from sender */
addr.sin_port=htons(HELLO_PORT);
/* bind to receive address */
if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0)
{
perror("bind");
exit(1);
}
/* use setsockopt() to request that the kernel join a multicast group */
mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
mreq.imr_interface.s_addr=htonl(INADDR_ANY);
if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0)
{
perror("setsockopt");
exit(1);
}
/* now just enter a read-print loop */
while (1)
{
/*if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,(struct sockaddr *) &addr,&addrlen)) < 0)
{
perror("recvfrom");
exit(1);
}
printf("the server says: %s\n",msgbuf);*/
printf("would you like to send?(y/n)\n");
scanf("%c",&ch);
fflush(stdin);
if(ch=='y')
{
printf("\nClient:");
gets(a);
printf("%c\n",a);
strcat(b2,a);
printf("%s\n",b2);
sendto(s,b2,sizeof(b2),0,(struct sockaddr *) &server,n);
b2[100]=NULL;
strcpy(b2,"1");
}
addrlen=sizeof(addr);
if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,(struct sockaddr *) &addr,&addrlen)) < 0)
{
perror("recvfrom");
exit(1);
}
printf("the server says: %s\n",msgbuf);
if(mysql_query(&mysql,msgbuf));
else
{
strcpy(re,"Client 1: ");
sendto(s,re,sizeof(re),0,(struct sockaddr *) &server,n);
//printf("inside else case\n");
result=mysql_store_result(&mysql);
//printf("\n after getting the result...\n");
num_fields = mysql_num_fields(result);
//printf("\n after getting numfields...\n");
while ((row = mysql_fetch_row(result)))
{
unsigned long *lengths;
//printf("\n inside while....\n");
lengths = mysql_fetch_lengths(result);
for(i = 0; i < num_fields; i++)
{
printf("[%.*s] \t", (int) lengths[i], row[i] ? row[i] : "NULL");
strcat(re,row[i]);
j++;
//printf("%d\n",j);
if(j==4)
{
//printf("the result is .....%s\n",re);
sendto(s,re,sizeof(re),0,(struct sockaddr *) &server,n);
memset(re,0,100);
strcpy(re,"Client 1: ");
j=0;
}
}
printf("\n");
}
}
}
}
I created an adhoc network and it assigned two ip address to the server and the client.
10.42.0.1/24 to the server and 10.42.0.47/24 to client
however the unicast operation from the client to the server is not functioning correctly neither is the multicast from the server to client.
secondly how do i determine whether both the programs are part of the same multicast group. The error on the client is either
setsockopt:invalid argument
or
setsockopt:no such device
Any help on the same is greatly appreciated..!!

There are a lot of potential bugs in your code:
Server:
1.You are not checking if the 's' socket was successfully created. However, your example will work without it since there is enough memory for socket creation.
2.You are not checking the return code from bind(), maybe you can't bind the socket to the port and that's why you get 'invalid argument' error
3.You are not checking the return code from recvfrom() ....
4.The IP 255.0.0.37 is reserved for future use, I am not sure it is valid, why not use a valid ip range?
5.For multicasting you have to use ip addresses in range: 224.0.0.0/4, not 10.0.0.0/8 since it is reserved for local networks.
And regarding the client, you should first make working udp protocol code, and then add mysql to it. You also have to tell us at which line you have the error, otherwise it is difficult to analyse the problem.

Related

program received signal sigsegv segmentation fault on using a pointer of a struct pointing to a structure placed on a shared memory

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define PORT 8080
#define SHM_SIZE 1024*(512+4)+100*((4*2)+(1024*2))+(4*4)
//---modes-----//
#define NOAUTO "NOAUTO"
#define AUTO "AUTO"
//---commands---//
#define SEND "SEND"
#define FETCH "FETCH"
#define FETCHIF "FETCHIF"
#define QUIT "QUIT"
#define EOF2 "EOF"
typedef char message[512];
typedef struct {
bool is_active;
int start_index;
int end_index;
bool indices[1024];
}circular_queue;
typedef struct {
message message_list[1024];
int last_index;
circular_queue connections[100];
int last_conn_index;
int remained_read[1024];
int num_conn;
int queue_start;
}multicast_queue;
int main(int argc, char const *argv[])
{
//-------------------connect to server-----------------//
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char shmid_s[512] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
read( sock , shmid_s, 512); //-----read shared memory information over socket-----//
int shmid = atoi(shmid_s);
printf("%d\n",shmid );
//---------------------attach to shared memory---------------------------//
if(shmid == -1)
{
perror("shmget");
exit(1);
}
multicast_queue *multicast_queue = shmat(shmid, (void*)0, 0);
if(multicast_queue == (void*)(-1))
{
perror("shmat");
exit(1);
}
int conn_no=multicast_queue->last_conn_index;
int read_index=multicast_queue->queue_start;
char *mode = NOAUTO;
printf("%s\n",mode);
char command[7];
memset(command,0,7);
message messagebody;
while(scanf("%s",command))
{
if(!strcmp(command,SEND))
{
printf("Enter the message to send: ");
scanf("%s", messagebody);
printf("%s %s\n", command, messagebody);
}
else if(!strcmp(command,FETCH))
{
message f_message;
memcpy(f_message, multicast_queue->message_list[read_index],512);
multicast_queue->remained_read[read_index]--;
if(multicast_queue->remained_read[read_index] == 0)
{
multicast_queue->queue_start = (multicast_queue->queue_start+1)%1024;
multicast_queue->connections[conn_no].start_index = (multicast_queue->connections[conn_no].start_index+1)%1024;
}
read_index++;
printf("%s\n", f_message);
}
}
return 0;
}
This is a client code piece of a UNIX domain stream socket project. The shared memory is created by the server code and shmid is send through the socket. Then, to use the shared memory, a pointer of the same type with the constructed data structure over the shared memory is set. Using this pointer the shared memory is attached to this client process. I get a segmentation error whenever i try to access a member of the multicast_queue which is attached to the shared memory (int conn_no=multicast_queue->last_conn_index;). I run this program on a virtual machine Ubuntu. I don't know what the reason behind getting this error is. I also increased the memory size for Ubuntu but it didn't work.

How to find the network interface used by a connected socket

How to find the interface used by a connected socket.So that i can set status codes for different interfaces.I used the below code.But I didnt get it.
I've tried two different approaches in the test code below, but both fail. The first one connects to a remote server, and uses ioctl with SIOCGIFNAME, but this fails with 'no such device'. The second one instead uses getsockopt with SO_BINDTODEVICE, but this again fails (it sets the name length to 0).
Any ideas on why these are failing, or how to get the I/F name? after compiling, run the test code as test "a.b.c.d", where a.b.c.d is any IPV4 address which is listening on port 80. Note that I've compiled this on Centos 7, which doesn't appear to have IFNAMSZ in <net/if.h>, so you may have to comment out the #define IFNAMSZ line to get this to compile on other systems.
Thanks.
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
int main(int argc, char **argv) {
int sock;
struct sockaddr_in dst_sin;
struct in_addr haddr;
if(argc != 2)
return 1;
if(inet_aton(argv[1], &haddr) == 0) {
printf("'%s' is not a valid IP address\n", argv[1]);
return 1;
}
dst_sin.sin_family = AF_INET;
dst_sin.sin_port = htons(80);
dst_sin.sin_addr = haddr;
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
return 1;
}
if(connect(sock, (struct sockaddr*)&dst_sin, sizeof(dst_sin)) < 0) {
perror("connect");
return 1;
}
printf("connected to %s:%d\n",
inet_ntoa(dst_sin.sin_addr), ntohs(dst_sin.sin_port));
#if 0 // ioctl fails with 'no such device'
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
// get the socket's interface index into ifreq.ifr_ifindex
if(ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
return 1;
}
// get the I/F name for ifreq.ifr_ifindex
if(ioctl(sock, SIOCGIFNAME, &ifr) < 0) {
perror("SIOCGIFNAME");
return 1;
}
printf("I/F is on '%s'\n", ifr.ifr_name);
#else // only works on Linux 3.8+
#define IFNAMSZ IFNAMSIZ // Centos7 bug in if.h??
char optval[IFNAMSZ] = {0};
socklen_t optlen = IFNAMSZ;
if(getsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &optval, &optlen) < 0) {
perror("getsockopt");
return 1;
}
if(!optlen) {
printf("invalid optlen\n");
return 1;
}
printf("I/F is on '%s'\n", optval);
#endif
close(sock);
return 0;
Idea based on another post
Create socket
Connect
Get interface address
Get interface id and name from interface address
$ gcc -std=gnu11 -Wall so_q_63899229.c
$ ./a.out 93.184.216.34 # example.org
interface index : 2
interface name : wlp2s0
interface address : 192.168.1.223
remote address : 93.184.216.34
so_q_63899229.c
#include <arpa/inet.h>
#include <assert.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
int sockfd=-1;
void connect2(const char *const dst){
sockfd=socket(AF_INET,SOCK_STREAM,0);
assert(sockfd>=3);
struct sockaddr_in sin={
.sin_family=AF_INET,
.sin_port=htons(80),
.sin_addr={}
};
assert(1==inet_pton(AF_INET,dst,&(sin.sin_addr)));
assert(0==connect(sockfd,(struct sockaddr*)(&sin),sizeof(struct sockaddr_in)));
}
void getsockname2(struct sockaddr_in *const sin){
socklen_t addrlen=sizeof(struct sockaddr_in);
assert(0==getsockname(sockfd,(struct sockaddr*)sin,&addrlen));
assert(addrlen==sizeof(struct sockaddr_in));
}
void disconnect(){
close(sockfd);
sockfd=-1;
}
void addr2iface_ifconf(const struct in_addr *const sin_addr,int *const index,char *const name){
struct ifconf ifc={
.ifc_len=0,
.ifc_req=NULL
};
int ioctlfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
assert(ioctlfd>=3);
assert(0==ioctl(ioctlfd,SIOCGIFCONF,&ifc));
const int sz=ifc.ifc_len;
assert(sz%sizeof(struct ifreq)==0);
const int n=sz/sizeof(struct ifreq);
char buf[sz];
bzero(buf,sz);
ifc.ifc_buf=buf;
assert(0==ioctl(ioctlfd,SIOCGIFCONF,&ifc));
assert(
ifc.ifc_len==sz &&
(char*)ifc.ifc_req==buf
);
for(int i=0;i<n;++i)if(0==memcmp(
&(((struct sockaddr_in*)(&(ifc.ifc_req[i].ifr_addr)))->sin_addr),
sin_addr,
sizeof(struct in_addr)
)){
*index=ifc.ifc_req[i].ifr_ifindex;
assert(name==strncpy(name,ifc.ifc_req[i].ifr_name,IFNAMSIZ));
return;
}
assert(0);
}
int main(int argc,const char *argv[]){
assert(argc==2);
assert(argv[1]&&strlen(argv[1]));
const char *const remoteaddr_s=argv[1];
// const char *const remoteaddr_s="93.184.216.34";
connect2(remoteaddr_s);
struct sockaddr_in ifaddr={};
getsockname2(&ifaddr);
disconnect();
int index=0;
char ifname[IFNAMSIZ]={};
addr2iface_ifconf(&(ifaddr.sin_addr),&index,ifname);
char ifaddr_s[INET_ADDRSTRLEN]={};
assert(ifaddr_s==inet_ntop(AF_INET,&(ifaddr.sin_addr),ifaddr_s,INET_ADDRSTRLEN));
printf("interface index : %d\n",index);
printf("interface name : %s\n",ifname);
printf("interface address : %s\n",ifaddr_s);
printf("remote address : %s\n",remoteaddr_s);
// printf("#%d %s %s -> %s\n",
// index,
// ifname,
// ifaddr_s,
// remoteaddr_s
// );
return 0;
}
Also there doesn't seem to be an identifier named IFNAMSZ. IFNAMSIZ defined in <net/if.h> should be the maxinum legth (including '\0') allowed for the name of any interface IMHO.

I am unable to print message recived from client side in c server using socket?

In debugging I can see that values of rx_buffer changes to what is send from client but printf function and even fputs function is not printng the value on terminal or updating the output file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
// Constants defined
#define SERVER_PORT 3333
#define RX_BUFFER_SIZE 1024
#define TX_BUFFER_SIZE 1024
#define MAXCHAR 1000 // max characters to read from txt file
// Global variables
struct sockaddr_in dest_addr;
struct sockaddr_in source_addr;
char rx_buffer[RX_BUFFER_SIZE]; // buffer to store data from client
char tx_buffer[RX_BUFFER_SIZE]; // buffer to store data to be sent to client
char ipv4_addr_str[128]; // buffer to store IPv4 addresses as string
char ipv4_addr_str_client[128]; // buffer to store IPv4 addresses as string
int listen_sock;
char line_data[MAXCHAR];
FILE *input_fp, *output_fp;
int socket_create(struct sockaddr_in dest_addr, struct sockaddr_in source_addr){
int addr_family;
int ip_protocol;
dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(SERVER_PORT);
addr_family = AF_INET;
ip_protocol = IPPROTO_IP;
int sock,p;
printf("Create the socket\n");
sock=socket(addr_family , SOCK_STREAM , 0);
if((bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)))<0){
perror("Bind failed.");
}
else{
printf("bind done");
}
char client[100];
listen(sock,1);
printf("Waiting for incoming connections...\n");
p = accept(sock, (struct sockaddr *)&source_addr, (socklen_t*)&source_addr);
if(p<0){ perror("accept failed");} printf("Client Address=%s\n",inet_ntop(AF_INET,&source_addr.sin_addr,client,sizeof(client)));
return p;
}
int receive_from_send_to_client(int sock){
char mess[10]="hello";
int len;
len=recv(sock , rx_buffer, sizeof(rx_buffer),0);
send(sock , mess , 5,0);
return 0;
}
int main() {
char *output_file_name = "data_from_client.txt";
// Create socket and accept connection from client
int sock = socket_create(dest_addr, source_addr);
output_fp = fopen(output_file_name, "w");
if (output_fp == NULL){
printf("Could not open file %s\n",output_file_name);
return 1;
}
while (1) {
receive_from_send_to_client(sock);
printf("%s",rx_buffer);
fputs(rx_buffer, output_fp);
fputs("\n", output_fp);
}
return 0;
}
In debugging I can see that values of rx_buffer are changing but not able to put that in file or print the message.
Note:- I am sending message from a python client.
in while ,you should open your file always and after putting data into the file close file descriptor properly.
see this code in main(),
int main() {
char *output_file_name = "data_from_client.txt";
// Create socket and accept connection from client
int sock = socket_create(dest_addr, source_addr);
while (1) {
output_fp = fopen(output_file_name, "a+");
if (output_fp == NULL){
printf("Could not open file %s\n",output_file_name);
return 1;
}
receive_from_send_to_client(sock);
printf("%s",rx_buffer);
fprintf(output_fp,"%s",rx_buffer);
fclose(output_fp);
}
return 0;
}

Recv() not working in separate thread, C socket programming

I am having some issues with the recv() function returning a -1 in a C program with threading. The basis of the program is to receive a few request packets in one thread and having a second thread send out a multicast to all registered clients.
Below is the code for my server:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <arpa/inet.h>
#include <pthread.h>
#define SERVER_PORT 5654
#define MAX_LINE 256
#define MAX_PENDING 5
/*structure of the packet*/
struct packet{
short type;
char data[MAX_LINE];
};
struct data_packet{
short header;
char data[MAX_LINE];
};
/* structure of Registration Table */
struct registrationTable{
int port;
char name[MAX_LINE];
int req_no;
};
struct global_table{
int sockid;
int reqno;
};
void *join_handler(struct global_table *rec){
int new_s;
struct packet packet_reg;
new_s = rec->sockid;
printf("In thread: %i\n",new_s);
printf("In thread: %i\n",rec->reqno);
if(recv(new_s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\ncouldnt receive first reg packet\n");
exit(1);
}
pthread_exit(NULL);
}
int main(int argc, char* argv[])
{
/* initilizing all of the packets*/
struct packet packet_reg;
struct registrationTable table[10];
struct global_table record[20];
struct sockaddr_in sin;
struct sockaddr_in clientAddr;
char buf[MAX_LINE];
int s, new_s;
int len;
int i;
struct hostent *he;
struct in_addr **addr_list;
pthread_t threads[2];
/* setup passive open */
if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0){
perror("tcpserver: socket");
exit(1);
}
/* build address data structure */
bzero((char*)&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);
if(bind(s,(struct sockaddr *)&sin, sizeof(sin)) < 0){
perror("tcpclient: bind");
exit(1);
}
listen(s, MAX_PENDING);
/* wait for connection, then receive and print text */
while(1){
if((new_s = accept(s, (struct sockaddr *)&clientAddr, &len)) < 0){
perror("tcpserver: accept");
exit(1);
}
/* print the port of the client*/
printf("\n Client's port is %d \n", ntohs(clientAddr.sin_port));
/* receive the first registration packet*/
if(recv(new_s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\ncouldnt receive first reg packet\n");
exit(1);
}
struct global_table client_info;
client_info.sockid = ntohs(clientAddr.sin_port);
client_info.reqno = 1;
pthread_create(&threads[0],NULL,join_handler, &client_info);
}
}
Client:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#define SERVER_PORT 5654
#define MAX_LINE 256
/*structure of the packet*/
struct packet{
short type;
char data[MAX_LINE];
};
struct data_packet{
short header;
char data[MAX_LINE];
};
int main(int argc, char* argv[])
{
struct packet packet_reg;
struct hostent *hp;
struct sockaddr_in sin;
char *host;
char buf[MAX_LINE];
int s;
int len;
char hostname[1024];
hostname[1023] = '\0';
if(argc == 2){
host = argv[1];
}
else{
fprintf(stderr, "usage:newclient server\n");
exit(1);
}
/* translate host name into peer's IP address */
hp = gethostbyname(host);
if(!hp){
fprintf(stderr, "unkown host: %s\n", host);
exit(1);
}
/* active open */
if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0){
perror("tcpclient: socket");
exit(1);
}
/* build address data structure */
bzero((char*)&sin, sizeof(sin));
sin.sin_family = AF_INET;
bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
sin.sin_port = htons(SERVER_PORT);
if(connect(s,(struct sockaddr *)&sin, sizeof(sin)) < 0){
perror("tcpclient: connect");
close(s);
exit(1);
}
/* main loop: get and send lines of text
all you have to do to start the program is
enter any key */
while(fgets(buf, sizeof(buf), stdin)){
/* Find the hostname and print it*/
gethostname(hostname, 1023);
printf("Hostname: %s\n", hostname);
/* populate the info for the first registration packet*/
packet_reg.type = htons(121);
strcpy(packet_reg.data,hostname);
/*send the registration packet to the server*/
if(send(s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\nsend failed\n");
exit(1);
}
/* Print the contents of the first registration packet*/
printf("Sent 1st reg packet data: %s\n",packet_reg.data );
printf("Sent 1st reg packet type: %i\n",ntohs(packet_reg.type));
/* create the second registration packet.
I created separate packets for this so
it was clearer*/
packet_reg.type = htons(121);
strcpy(packet_reg.data,hostname);
/*send the second registration packet to the server*/
if(send(s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\nsend failed\n");
exit(1);
}
/* Print the contents of the second registration packet*/
printf("Sent 2nd reg packet data: %s\n",packet_reg.data );
printf("Sent 2nd reg packet type: %i\n",ntohs(packet_reg.type));
}
}
So Basically, I am creating the connection and wait to receive the first registration packet (packet_reg). This works and I receive the packet. I then send control of the program to the thread. However, while the "rec" variable correctly passes the information, the subsequent receive does not work and exits with a value less than 0.
Other information: The packets are all sent and received correctly, but the client's port, printed from
printf("\n Client's port is %d \n", ntohs(clientAddr.sin_port));
is listed as 0. I am not sure if this is a problem, but the code works fine when all of the receives are in the main function.
Another issue could be that I get the following warning:
passing argument 3 pf pthread_create from incompatible pointer type expected 'void * (*) (void *)' but argument of type 'void * (*) (struct global_table*)'
I have researched this warning and know that it has to do with receiving the data as void and then casting. However, the data is being sent to the thread properly when I print from there to check.
Basically, the problem is that while I can receive the packets from the client outside the thread, with the same statements, when I am inside the thread the packets are not received and recv() returns -1.
I accidentally set the receive to the port and not the socket. I am a dummy. I know that a lot of you were telling me how bad the code is constructed regarding TCP conventions. I am building off of code for an assignment, nothing I can do about the professor telling us that this is the way to do it.

Check port reachable in C

I have a C function to check a host and its port, when I use FQDN host name, the function return error like: connect() failed: connect time out, but if I use IP address instead, it seems ok, how to fix this?
Thanks.
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
int is_network_up(char *chkhost, unsigned short chkport) {
int sock;
struct sockaddr_in chksock;
struct hostent *host = NULL;
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
syslog(LOG_ERR, "socket() creation error: %s", strerror(errno));
return 0;
}
memset(&chksock, 0, sizeof(chksock));
chksock.sin_family = AF_INET;
chksock.sin_port = htons(chkport);
/* get the server address */
if (inet_pton(AF_INET, chkhost, &(chksock.sin_addr.s_addr)) <= 0) {
if ((host = gethostbyname(chkhost)) == NULL) {
syslog(LOG_ERR, "%s", hstrerror(h_errno));
return 0;
}
memcpy(&(chksock.sin_addr.s_addr), &(host->h_addr_list[0]),
sizeof(struct in_addr));
}
/* try to connect */
if (connect(sock, (struct sockaddr *) &chksock, sizeof(chksock)) < 0) {
syslog(LOG_ERR, "connect() failed: %s", strerror(errno));
return 0;
}
close(sock);
return 1;
}
inet_pton() is the wrong task for that. It only accepts numerical addresses.
In former times, people used to use gethostbyname() for name resolution.
But as we have 2012 meanwhile, this method is outdated for several years now, as it is still restricted to AF_INET.
With the program below, you should achieve about the same and stay future compatible.
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
int is_network_up(char *chkhost, unsigned short chkport) {
int sock = -1;
struct addrinfo * res, *rp;
int ret = 0;
char sport[10];
snprintf(sport, sizeof sport, "%d", chkport);
struct addrinfo hints = { .ai_socktype=SOCK_STREAM };
if (getaddrinfo(chkhost, sport, &hints, &res)) {
perror("gai");
return 0;
}
for (rp = res; rp && !ret; rp = rp->ai_next) {
sock = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sock == -1) continue;
if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) {
char node[200], service[100];
getnameinfo(res->ai_addr, res->ai_addrlen, node, sizeof node, service, sizeof
service, NI_NUMERICHOST);
printf("Success on %s, %s\n", node, service);
ret = 1; /* Success */
}
close(sock);
}
freeaddrinfo(res);
return ret;
}
int main(int argc, char** argv) {
if (argc > 1) {
printf("%s: %d\n", argv[1], is_network_up(argv[1], 22));
}
}
Make sure name resolution is working. See if you can ping the machine by name from the exact same environment in which your code runs.
If ping works, try telnet <machinename> <portnumber> -- If both of those work it is likely a problem with your code (which I did not look at in depth, too sleepy:).
Make sure you're converting anything returned by the OS as an ip address from network order to host order. IIRC, gethostbyname returns binary ip addresses in network order.
ntohl can be used on chksock.sin_addr.s_addr after the memcpy to achieve this.

Resources