I'm having a problem with running a small block of code. This is regarding socket programming in C. What I'm trying to do is have a client communicate to a server on two different ports. But when i'm trying to compile the client code, i get 'segmentation fault'. I'm giving my client code here. Please let me know what's going wrong.
#include<stdio.h>
#include<stdbool.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int main(int argc,char *argv[])
{
int sockfd,newsockfd,sockfd_infinite,sockfd_kitchen,portno,portno1,n,no_of_tables;
struct sockaddr_in serv_addr,kitchen_addr;
struct hostent *server,*kitchen;
struct timeval time_out;
time_out.tv_sec = 15; // 15 seconds
time_out.tv_usec = 0; // 0 milliseconds
// server=gethostbyname(argv[1]);
// char buffer[256];
portno=atoi(argv[2]);
portno1=atoi(argv[4]);
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1)
error("\nError creating socket");
server=gethostbyname(argv[1]);
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(portno);
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
sockfd_kitchen=socket(AF_INET,SOCK_STREAM,0);
if(sockfd_kitchen==-1)
error("\nError creating socket");
kitchen=gethostbyname(argv[3]);
kitchen_addr.sin_family=AF_INET;
kitchen_addr.sin_port=htons(portno1);
bcopy((char *)kitchen->h_addr,
(char *)&kitchen_addr.sin_addr.s_addr,
kitchen->h_length);
n=connect(sockfd_kitchen,(struct sockaddr *)&kitchen_addr,sizeof(kitchen_addr));
if(n==-1)
error("\nError connecting to kitchen");
n=connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
if(n==-1)
error("\nError connecting to server");
return 0;
}
So the idea behind this code is - there is a client and there is a server. This client wants to communicate with the server on two different ports as if the client is talking to two different servers. I'm doing this on my laptop giving in the server names as 'localhost' for both the server names and different port numbers. Like you see in my code, I have two pointer variables for the two servers namely, *server and *kitchen.
Eg:
./thiscode localhost 15535 localhost 12345
In the example I've mentioned, this is how I'm compiling my client code. argv[1] is the first "localhost" (server name) and argv[2] is the port number of the first server. The second "localhost" and '12345' are the second server's name and port number.
Like I've said before, I'm trying to have three windows on my laptop running three different codes (one for client and two for servers). My two server codes compile without any problem but my client code gets this 'segmentation' fault. Please let me know where I'm going wrong.
Thanks.
For a start, you should be checking the return values from gethostbyname:
The gethostbyname() and gethostbyaddr() functions return the hostent structure or a NULL pointer if an error occurs. On error, the h_errno variable holds an error number.
It seems that the problem is in bcopy() function call.
You have not declared space for the variable before copying stuff into it, and hence you saw a segmentation fault.
Enter the following code before the bcopy() statement to remove the Seg-fault:
serv_addr.sin_addr.s_addr=malloc(sizeof(unsigned long));
Related
So I was trying to understand socket programming in C when I came across this code:
/* Sample UDP client */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char**argv)
{
int sockfd,n;
struct sockaddr_in servaddr;
char sendline[] = "Hello UDP server! This is UDP client";
char recvline[1000];
if (argc != 2)
{
printf("usage: ./%s <IP address>\n",argv[0]);
return -1;
}
sockfd=socket(AF_INET,SOCK_DGRAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=inet_addr(argv[1]);
servaddr.sin_port=htons(32000);
sendto(sockfd,sendline,strlen(sendline),0,(struct sockaddr *)&servaddr,sizeof(servaddr));
n=recvfrom(sockfd,recvline,10000,0,NULL,NULL);
recvline[n]=0;
printf("Received: %s\n",recvline);
return 0;
}
It seems that the recvfrom() call does not need an ip address to send the message. A look at the man pages revealed the following lines:
If src_addr is not NULL, and the underlying protocol provides the
source address, this source address is filled in. When src_addr is
NULL, nothing is filled in; in this case, addrlen is not used,
and should also be NULL.
So I think that the underlying protocol provides the source IP address. My problem is, how does it really figure out the address to receive the message from ? Is it that, once you send a message to an address, you cannot use the same socket to send messages to other addresses ? So that it keeps on using the same address ?
Please help. Couldn't find an answer anywhere in Google or any lecture note.
Thank you in advance.
You have a misconception that recvfrom pulls data from a particular source address.
recvfrom is generally used for connectionless protocols like UDP. When an UDP packet is received, it could be from any source address. src_addr returns this address for the application usage.
If you are expecting messages only from a particular address, there are 2 ways. (1) Either you can ignore the packets received from other addresses by comparing the address returned in src_addr, or (2) use connect to specify a particular remote address from where you are expecting messages and the lower socket layer takes care of ignoring packets from other sources. After connect, you could also use recv instead of recvfrom.
Sending messages are done through sendto. You seem to be confusing the 2 calls. Using sendto it is possible to send messages to difference addresses on the same socket.
I am new to winsock2 and networking in general but I am not new to C.
My goal is to make a program that can send and receive data from one computer to another.
Basically I want to make something like this:
Computer one initializes a transfer with computer two. Computer one does know the IP address of computer two but computer two does not know the IP address of computer one. So in other words computer two can be though of as a server and computer one as a client.
I would like for this to work without either of the users need to mess with router settings such as forwarding ports. My idea was to make something like an HTTP server. The reason for this is because pretty much all routers can view webpages which regularly send and receive data which is my goal. And just like what I want to do, the server does not know the clients IP address until the client tries to request something from the server. So with that said I realize that I should model my program off of HTTP. I decided to first write a simple program testing the programs ability to send a webpage.
#include <Winsock2.h>
#include <windows.h>
#include <stdio.h>
static const char html[]="HTTP/1.1 200 OK\r\n"
"Connection: close\r\n"
"Content-type: text/html\r\n\r\n"
"<html>\r\n"
"<head>\r\n"
"<title>Html Test</title>\r\n"
"</head>\r\n"
"<body>\r\n";
static const char htmlend[]="</body>\r\n"
"</html>\r\n\r\n";
static const char * defaultStr="Default";
int main(void){
int exit=0;
WSADATA wsa;
char buffer[512];
int bytes;
SOCKET s,client;
SOCKADDR_IN localAddress;
WSAStartup(MAKEWORD(2,2),&wsa);
while(!exit){
char * str;
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
localAddress.sin_family = AF_INET;
localAddress.sin_port = htons(80);
localAddress.sin_addr.s_addr = INADDR_ANY;
bind(s, (SOCKADDR*)&localAddress, sizeof(localAddress));
listen(s, SOMAXCONN);
client = accept(s,NULL,NULL);
closesocket(s);
bytes = recv(client,buffer,512,0);
fputs(buffer,stdout);
str=strstr(buffer,"GET /")+5;
if(str){
char *str3;
if(*str==' '){
str=(char*)defaultStr;
}else{
char *str2=strstr(str," ");
*str2=0;
if(!strcmp(str,"Exit"))
exit=1;
}
puts(str);
str3=malloc(strlen(html)+strlen(htmlend)+strlen(str)+6);
strcpy(str3,html);
strcat(str3,str);
strcat(str3,"\r\n");
strcat(str3,htmlend);
fputs(str3,stdout);
send(client,str3,strlen(str3),0);
free(str3);
}
shutdown(client,SD_BOTH);
closesocket(client);
}
WSACleanup();
return 0;
}
The issue with the above program is that it works only on internal network. When I try to access it on the world wide web nothing happens. Am I even taking the right approach (simulating http for P2P?)? What is wrong with my program that it does not work on the world wide web? If anyone has an answer to either or both of these questions I thank you in advanced.
Following code is TCP server program just send back “HELLO!!” to client.
When I run server with port 80, bind() is returned Permission denied.
Port 12345 is OK.
How can I use port 80 for this server program?
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int
main(){
int sock0;
struct sockaddr_in addr;
struct sockaddr_in client;
int len;
int sock;
char *message;
message = "HELLO !!";
sock0 = socket(AF_INET,SOCK_STREAM,0);
addr.sin_family = AF_INET;
addr.sin_port = htons(80);
inet_pton(AF_INET,"127.0.0.1",&addr,sizeof(addr));
bind(sock0,(struct sockaddr *)&addr,sizeof(addr));
perror("bind");
len = sizeof(client);
sock = accept(sock0,(struct sockaddr *)&client,&len);
perror("accept");
write(sock,message,sizeof(message));
perror("write");
close(sock);
return 0;
}
Ports below 1024 are considered "privileged" and can only be bound to with an equally privileged user (read: root).
Anything above and including 1024 is "free to use" by anyone.
OT: you may know this already, but the port in your example is that for HTTP web servers. Anything listening to this port should speak HTTP, too. A simple "hello world" does not suffice. ;-)
Only the root user is allowed to bind to ports <= 1024. Every ports > 1024 can be bound to by normal users.
Try executing your program as root or with sudo.
you have to run your application with super user account (root)
Run your application with sudo command
I know there are a few similar question on SO, but I feel like everyone has a different issue that is causing this. So I'm posting my particular case.
I'm working on the raspberry pi, using raspbian, a debian derivative. I'm coding in ansi C. This is a server that sends some data to a udp client on another end through port 500.
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
int main()
{
int sockfd;
struct sockaddr_in servaddr,cliaddr;
socklen_t clilen;
char buffer[256];
sockfd=socket(AF_INET,SOCK_DGRAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(500);
bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
sprintf(buffer,"hi this is a test \n");
if(sendto(sockfd,buffer,sizeof(buffer),0,(struct sockaddr *)&cliaddr,sizeof(cliaddr))==-1)
{ error("fail:")
};
return 0;
}
But this just gives me the error "invalid arguments", I can't figure out what could possibly be wrong. If the type of argument I supply to sendto is incorrect, this would fail on compile. But the type is correct and this compiles, only at runtime does it fail.
You have no initialization for the cliaddr structure. Thus, its contents are random. Your code compiles fine because you have a struct sockaddr_in where it should be but the compiler cannot check if you have properly initialized it.
On the other hand, at runtime when sendto is invoked the glibc or the kernel finds out that that random data in the cliaddr structure doesn't look like a valid address and throws up an invalid argument error.
Solution: initialize the cliaddr variable before using it.
Edit: You also need to properly initialize the socket, the third argument there shouldn't be 0.
Second edit, read me: For resources I recommend the extraordinary guide of Beej. For your exact problem this subchapter can help.
I'm not a software person, but I could really use some advice.
I'm writing a C program (cut/paste below) to establish a TCP socket connection from my Mac Pro to a Windows XP-based test-instrument sitting next to it over LAN (Ethernet). The program compiles without any warnings or errors. But executing the code using GNU Debugger, I can see it exits at 'exit(2)' which is the "if(connect(MySocket" line. There's no timeout, it just exits immediately.
I compile using:
gcc -g -Wall talk2me.c -o talk2me
but I don't get any hints in the output nor when debugging at to what might be the issue.
I'm sure the 10.0.1.100 and port 5025 are correct (using Matlab code I can communicate fine using these parameters). Any idea where else I could look to debug?
Outside of the code itself, are there any other requirements (perhaps system-level) that need to be satisfied (like running the code from a certain directory, or setting a parameter in unix to allow connections, etc.)? It may be something obvious that I'm missing because I'm a hardware guy, so feel free to assume I'm doing something stupid. I can run a 'hello world' program fine, it that helps. Thanks in advance, ggk
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <arpa/inet.h> //for inet_addr
#include <unistd.h> // for function 'close'
int main(void)
{
int MySocket;
if((MySocket=socket(PF_INET,SOCK_STREAM,0))==-1) exit(1);
struct in_addr {
unsigned long s_addr;
};
struct sockaddr_in {
short int sin_family; // Address family
unsigned short int sin_port; // Port number
struct in_addr sin_addr; // Internet address
unsigned char sin_zero[8]; // Padding
};
struct sockaddr_in MyAddress;
// Initialize the whole structure to zero
memset(&MyAddress,0,sizeof(struct sockaddr_in));
// Then set the individual fields
MyAddress.sin_family=PF_INET; // IPv4
MyAddress.sin_port=htons(5025); // Port number used by instrument
MyAddress.sin_addr.s_addr=inet_addr("10.0.1.100"); // IP Address
if(connect(MySocket,(struct sockaddr *) &MyAddress,
sizeof(struct sockaddr_in))==-1) exit(2);
// Send SCPI command
if(send(MySocket,"*IDN?\n",6,0)==-1) exit(3);
// Read response
char buffer[200];
int actual;
if((actual=recv(MySocket,&buffer[0],200,0))==-1) exit(4);
buffer[actual]=0; // Add zero character (C string)
printf("Instrument ID: %s\n",buffer);
// Close socket
if(close(MySocket)==-1) exit(99);
return 0;
}
You have defined struct in_addr and struct sockaddr_in yourself at the top of main. Do not do that, these are types found in header files(netinet/in.h), you have to use those, not your own versions.
Try connection with telnet from your mac box to 10.0.1.100 port 5025 , does that work ?
replace that exit(2); with {perror("connect"); exit(2); } to get a description of what is wrong.