For connecting to a web server I use below code in C:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#define PORT 4455
void main()
{
int clientSocket;
struct sockaddr_in serverAddr;
char buffer[1024];
clientSocket=socket(PF_INET,SOCK_STREAM,0) ;
printf("[+]client socket created successfully.\n");
memset(&serverAddr,'\0',sizeof(serverAddr));
serverAddr.sin_family=AF_INET;
serverAddr.sin_port=htons(PORT);
serverAddr.sin_addr.s_addr=inet_addr("https://www.google.com/");
connect(clientSocket,(struct sockaddr*)&serverAddr,sizeof(serverAddr));
printf("[+]connected to the server\n");
recv(clientSocket,buffer,1024,0);
printf("[+]data received is %s\n",buffer);
printf("[+]closing the connection\n");
}
But when I compile and run the code, it doss not receive any data, or the received data is not valid.
For example, received data from Google is :
��5��
How can I fix it?
You're not checking the return values from your networking function calls, so you have no idea whether they succeeded or failed. It's possible that all your calls failed, and your code is just printing the random data in the uninitialized array buffer.
In addtion, you're doing a lookup for https://google.com, which is a URI, not an address. Most likely inet_addr() is not the right function to resolve a name to an IP address, even if you had an IP address, which you don't. You probably need to start with gethostbyname().
Most importantly, even if you do manage to make a network connection to Google's HTTPS service, you'll be dealing with encrypted data, so you won't be able to process it unless you set up a encrypted TLS session. That's a long way from being straightforward, and most people use libraries like OpenSSL for this kind of thing.
I suspect that some of the problems I've noticed could have been spotted by your C compiler, if you turned its warning level up.
If you want to practice socket programming, I'd recommend that you start with a server that accepts simple, plaintext communication. If you want to practice socket programming with encryption, I'd recommend that you investigate OpenSSL or some similar library, or settle in for a lot of hard work. If you just want to make HTTP requests from your application, whether encrypted or not, I'd suggest looking at library like libcurl, which makes this kind of thing very easy.
There are loads and loads of C socket programming examples, on SO and many other places, if you need inspiration.
Related
I want to write basic chat program. I don't release that, I just want to learn socket programming. The chat program will be between client and server.
server code:
//bla bla code
new_socket = accept(server_fd, (struct sockaddr*)&address,(socklen_t*)&addrlen);
char server_msg[128];
char client_msg[128];
int running = 1;
while(running){
fgets(server_msg, 64, stdin);
send(new_socket, server_msg, strlen(server_msg), 0);
recv(new_socket, client_msg, 128, 0);
}
client code:
char server_msg[128];
char client_msg[128];
int running = 1;
while(running){
fgets(client_msg, 64, stdin);
send(server_socket, client_msg, strlen(client_msg), 0);
recv(server_socket, server_msg, 128, 0);
}
Questions:
Is the new socket fd used only once? That means; Will I do create a new socket for each sending and receiving. Or can I use this forever?
If first question answer is "FOREVER", Will I do something to new socket fd? I don't know maybe clear.
The above code is not working as expected. As I expected. Actually, The code is working very well :D. How do I perform interrupt operations such as getting input, sending messages, receiving messages?
My English is not good, I'm sorry.
Is the new socket fd used only once? That means; Will I do create a new socket for each sending and receiving. Or can I use this forever?
you open a TCP socket connection, so, once in the connected state (the ESTABLISHED state) it remains there until one side closes it (and the other side will notice it by reading 0 bytes as result, this explanation is oversimplified to make it simpler to your case, normally you should detect the end of file in the socket, so you can close it, and accept(2) another connection)
If first question answer is "FOREVER", Will I do something to new socket fd? I don't know maybe clear.
Your program is not a chat program, as the server uses the SAME socket to write what it has read, so it will return the message sent to the same client that issued it (acting more as an echo server, than a chat)
The above code is not working as expected. As I expected. Actually, The code is working very well :D. How do I perform interrupt operations such as getting input, sending messages, receiving messages?
Normally, a chat server should wait for a message to arrive at several sockets (by means of the select(2) system call) and will determine which socket needs attention. As a result, the server will read(2) from that socket (probably in a non blocking way, to avoid being blocked on a read to a socket, that will not be interrupted if data enters on another socket) The chat server should write what it has read over all the other sockets it has connections from, so every other user of your chat system receives a copy of the message (sending back the message to the sender is optional, but not very elegant, the issuer of the message should do local echo of it, although, to ensure the user sees his messages interspersed between the ones from other users)
I recommend you to read the book "Unix Network Programming" from Richard Stevens. It describes perfectly how to use the sockets API and IMHO it is the best reference you can get to learn how to use the socket interface.
One final note:
Don't use plain numbers hardwired in your code, as it is error prone (you declare a buffer string to be 128 bytes, but then read only 64, making 64 unused bytes in the array, you can use sizeof buffer as to make the compiler to use the amount declared in the variable, or you can #define BUFFSIZE 128 and then declare char buffer[BUFFSIZE]; and later do a fgets(buffer, BUFFSIZE, socket_FILE_descriptor); if you use a constant to size a buffer, use a constant name to name it :) and use it everywhere, in case you decide to give it a different value, all the occurences of it will change, instead of having to reviste all places in your code where you have used the number 64.
Hello and good evening,
I am writing a client & server pair of programs in C. Right now I got both of them running and by providing access to ports on my server through router settings, I can establish local and global connections for a barebones chat back and forth. Here is what both programs do until now.
Client:
create a socket
create an sockaddr_in (port and IP address)
connect the socket with the sockaddr_in to the server
go into a loop for read / write to the server, one at a time
Server:
create a socket
create a sockaddr_in (port and IP address)
bind the socket to sockaddr_in
listen to request on the socket
accept a request
go into a loop for read / write to the server, one at a time
My question:
What do I have to consider for handling and error-handling these individual steps correctly?
What I got until now is code like this:
printf("trying to connect to: IPv4 <%s> port <%s> ...", argv[1], argv[2]);
if(connect(net_socket, (struct sockaddr *)&server_address, sizeof server_address) == -1)
{
fprintf(stderr, "\ntcp connection failed.\n");
exit(4);
}
printf(" success.\nconnection to server: IPv4 <%s> port <%s>\n", argv[1], argv[2]);
Code like this is wrapped around all the steps these programs do from socket creation to connect and accept. And they work given the right input.
I want to scale my programs:
simultaneous read and write for both sides
multiple clients to server instead of client and server
correct data encapsulation
etc.
For that I need to know how to do the backbone correct and I want to get the basics straight before I start multithreading, forking, selecting or building whatnot around the core.
I don't want to overscale this post, hence I will only post my code if it is requested at all. Thank you very much for reading and replying in advance.
First off, it's always good practice to wrap all error/loging functions so they can be modified for later scaling. I do this so, later I can add file/line to my errors.
void perr(char *message)
{
fprintf(stderr, message);
}
On to your question. It's a very practice-rich answer. (Better asked on this board. But I'll help you anyways.
You're right to have the backbone as solid as possible before expanding. The best practice for a well made application is to have it very 'flat' in scope. (not to many if's in if's). Doing this will also provide you with a better understanding of the flow of code and more atomic error reporting:
main()
{
if(!(soc = createsocket(...)) return 1;
if(!bindsocket(soc))
{
deletesocket(soc);
return 1;
}
// Main server loop
while(req = accept_request(soc))
{
proc_request(req);
}
plog("No longer accepting request");
return 0;
}
Notice how I have no error reporting in the driver function (main in this example). This is because all error reporting is handled INSIDE of the called functions (createsocket(), bindsocket(), ect).
The driver function is only concerned if the called functions succeeded or not. The details of each failure are best described in the function who's arguments lead to the failure.
Here are my tips:
Avoid exit(), your code needs to be ready to use return all the way up to main() if something goes wrong. There are execptions (threads and child procs, but you get the idea)
Good programs are good at failing
For a server/client relationship, the server is typically single threaded and only loops through all client requests (computers are faster than you think, unless you're expecting around 5k requests).
State Machines are extremely useful in your situation. Think of the states your program is going to be in between start and stop, lay out what methods need to be in each state and have an overall plan what happens with errors in each state. (ie, opened, establishing, running, stopping)
I'm not an expert in C programming, but I'm trying to write a fairly simple program using sendmsg() and recvmsg() to send a message between a client and a server (both are on the same machine, so basically I'm sending a message to localhost).
After initialising the required structures (as in the iovec and the msghdr) and succesfully connecting the client to the server, my sendmsg() call fails with "no buffer space avaliable" errno.
This is what linux man reports about this type of error:
The output queue for a network interface was full. This generally indicates that the interface has stopped sending, but maybe caused by transient congestion. (Normally, this does not occur in Linux. Packets are just silently dropped when a device queue overflows.)
I looked around on the Internet and as a result I found out that sendmsg() is not widely used, and nobody could relate with this type of error. The only useful advice I found was to check a possible excess of open sockets, but again I always close EVERY socket I create.
So I'm stuck, basically because being quite the noob I don't know exactly where to look to fix this kind of problem.
If anybody knows how to proceed, it would be great.
(And please don't tell me not to use sendmsg(), because the whole purpose of my work is to understand this syscall, and not send a message to myself)
Here's the code I've written so far on pastebin: client and server
--SOLVED--
Thank you very much. I've been able to solve the problem and I fixed other mistakes I made, so here's the functioning code for sendmsg() and recvmsg() working message-passing: Client and Server
As others have pointed out, iovlen should be 1. But also, you want to zero out mh before initializing some of its fields since you're probably sending in garbage in the uninitialized fields and the syscall gets confused. Also, it doesn't really make sense to set msg_name and msg_namelen since you're connected and can't change your mind about where to send the data anyway.
This is what works for me in your client code:
/* The message header contains parameters for sendmsg. */
memset(&mh, 0, sizeof(mh));
mh.msg_iov = iov;
mh.msg_iovlen = 1;
printf("mh structure initialized \n");
The msg_iovlen field contains the number of elements in the iov array, not its size in bytes.
The system interpreted the following uninitialized memory as iov elements, ended up with a packet that is larger than the socket buffer space available, and thus refused to send the data.
Okay, so in your code I found this:
mh.msg_iovlen = sizeof(iov);
Which sets the msg_iovlen member to the size of struct iovec. But the documentation says this about this field:
size_t msg_iovlen; /* # elements in msg_iov */
So your code is wrong, it tells sendmsg() that it's going to send way more elements than you actually initialize.
I know this question has been asked a million times in one form or another, but no question gave me a POSIX-compliant way of doing it.
I need to get the local network address of my computer without using getifaddrs or any other non POSIX-compliant way of accessing interfaces. Is that possible ?
There is no direct support for such a thing but you can use udp sockets (SOCK_DGRAM) to connect to a known distant address. Since udp sockets are stateless this doesn't do any network traffic.
Then you can query for the local endpoint of that socket (getsockname) to obtain the local IP adress through which your system would route. Again since udp is stateless this just queries your local routing tables and no real network traffic is issued.
Don't forget to close the socket after that.
Remote public nameservers are good for that purpose. You can test for several of them
one of them might occasionally be down or there might be no route for
some reason to that part of the world
your process may be on the same local network as the server and you
might only obtain some special local address
test for IPv4 and IPv6 addresses
No, that is not possible, as posix does not specify any API to access that information.
Unixes typically support getifaddrs, or the SIOCGIFCONF ioctl , so use one of them or some other system demendant API. Note that there can be (and usually are) several network interfaces on a machine, and you have to figure out which you're interested in.
Quite simple, surely:
#include <unistd.h>
int main(int argc, char* argv[]) {
return 8 == write(1, "0.0.0.0\n", 8) ? 0 : 1;
}
POSIX has no concept of "network", even less IP. So no.
Besides, a machine can have lots of network addresses (at least loopback, one or several for each network card, at least three IPv6 addresses, ...), "the network address" isn't well defined anyway.
#include <stdio.h>
int main(int argc, char* argv[]) {
printf("127.0.0.1\n");
}
I am writing an API which includes IPC functions which send data to another process which may be local or on another host. I'd really like the send function to be as simple as:
int mySendFunc(myDataThing_t* thing, int sd);
without the caller having to know -- in the immediate context of the mySendFunc() call -- whether sd leads to a local or remote process. It seems to me that if I could so something like:
switch (socketFamily(sd)) {
case AF_UNIX:
case AF_LOCAL:
// Send without byteswapping
break;
default:
// Use htons() and htonl() on multi-byte values
break;
}
It has been suggested that I might implement socketFamily() as:
unsigned short socketFamily(int sd)
{
struct sockaddr sa;
size_t len;
getsockname(sd, &sa, &len);
return sa.sa_family;
}
But I'm a little concerned about the efficiency of getsockname() and wonder if I can afford to do it every time I send.
See getsockname(2). You then inspect the struct sockaddr for the family.
EDIT: As a side note, its sometimes useful to query info as well, in this case info libc sockets
EDIT:
You really can't know without looking it up every time. It can't be simply cached, as the socket number can be reused by closing and reopening it. I just looked into the glibc code and it seems getsockname is simply a syscall, which could be nasty performance-wise.
But my suggestion is to use some sort of object-oriented concepts. Make the user pass a pointer to a struct you had previously returned to him, i.e. have him register/open sockets with your API. Then you can cache whatever you want about that socket.
Why not always send in network byte order?
If you control the client and server code I have a different suggestion, which I've used successfully in the past.
Have the first four bytes of your message be a known integer value. The receiver can then inspect the first four bytes to see if it matches the known value. If it matches, then no byte swapping is needed.
This saves you from having to do byte swapping when both machines have the same endianness.