There is my function. I pass argument port as 80 and I always can not bind socket.
int create_socket(int port)
{
int sock;
struct sockaddr_in name;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
fprintf(stderr, "Can not create socket\n");
return -1;
}
//Assigning a name to the socket
name.sin_family = AF_INET;
name.sin_port = htons((unsigned short)port);
name.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (const struct sockaddr *) &name, sizeof(name)) == -1) {
fprintf(stderr, "Can not bind socket\n");
return -1;
}
return sock;
}
Typically port number less than 1024 are used by well known network servers and in linux, root privilege is required to open these ports.
80 is HTTP port and so your program requires root privilege.
Related
This question already has answers here:
Socket programing Permission denied
(3 answers)
Closed 7 years ago.
I'm trying to write a program that receive the port number as a command-line argument and start an HTTP server. I'm passing a listenfd to accept() to do this. However, I'm getting a permission denied from my open_listenfd() then a bad descriptor error from Accept().
The open_listenfd() and Accept() functions are copied from
http://csapp.cs.cmu.edu/2e/ics2/code/src/csapp.c
I'm passing port 100 to the program:
int open_listenfd(int port)
{
int listenfd, optval=1;
struct sockaddr_in serveraddr;
/* Create a socket descriptor */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return -1;
/* Eliminates "Address already in use" error from bind */
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int)) < 0)
return -1;
/* Listenfd will be an endpoint for all requests to port on any IP address for this host */
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);
if (bind(listenfd, (SA *)&serveraddr, sizeof(serveraddr)) < 0)
return -1;
/* Make it a listening socket
* ready to accept connection
* requests */
if (listen(listenfd, LISTENQ) < 0)
return -1;
return listenfd;
}
int Open_listenfd(int port)
{
int rc;
if ((rc = open_listenfd(port)) < 0)
unix_error("Open_listenfd error");
return rc;
}
int Accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
int rc;
if ((rc = accept(s, addr, addrlen)) < 0)
unix_error("Accept error");
return rc;
}
int main(int argc, char **argv) {
int listenfd, connfd, port, clientlen;
struct sockaddr_in clientaddr;
struct hostent *phost;
char *phostaddr;
port = atoi(argv[1]);
listenfd = Open_listenfd(port);
clientlen = sizeof(clientaddr);
connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);
printf("%d\n", connfd);
printf("%s\n", strerror(errno));
return 0;
}
Another question is that if I want to the server to constantly accept() connections, read requests of the form
GET /path HTTP/1.1\r\n\r\n
How do I do this?
Ports below 1024 are considered to be privileged in Linux, so you're going to need be the root user to open a socket on a ports < 1024
I created a server socket in C. This is the most basic stuff like what you would fine in a simple TCP server example. Server code is below. I also created a client socket that runs on the host machine. Code also below. However, for some reason the client is not able to connect to the server. The IP address I used is the same as the one under the entry eth0 from the "ip addr" command. The network adapter of the VM is a bridged connection.
The exact same code works when both client and server run on the same machine (the host).
Thank you!
Server code:
int sockfd;
int clientfd;
struct sockaddr_in self;
struct sockaddr_in client_addr;
int addrlen = sizeof (client_addr);
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket");
return EXIT_FAILURE;
}
printf("Socket descriptor is: %d\n", sockfd);
memset(&self, 0, sizeof (self));
self.sin_family = AF_INET;
self.sin_port = htons(MY_PORT);
self.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr*) &self, sizeof (self)) != 0) {
perror("socket--bind");
return EXIT_FAILURE;
}
if (listen(sockfd, 20) != 0) {
perror("socket--listen");
return EXIT_FAILURE;
}
clientfd = accept(sockfd, (struct sockaddr*) &client_addr, &addrlen);
printf("%s:%d connected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
Client Code:
int sock;
struct sockaddr_in server;
//struct sockaddr_in client;
struct hostent *hp;
//char buf[BUFFER_SIZE];
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
die(6, "Opening stream socket");
printf("Client socket file descriptor is: %d\n", sock);
memset(&server, (char) 0, sizeof (server));
server.sin_family = AF_INET;
hp = gethostbyname(host_name);
if (!hp) {
//sprintf(buf, "%s: unknown host\n", host_name);
die(8, "%s: unknown host\n", host_name);
}
memcpy(hp->h_addr, &server.sin_addr, hp->h_length);
server.sin_port = htons((u_short) SERVER_PORT);
/* Try to connect */
if ((connect(sock, (struct sockaddr *) &server, sizeof (server))) < 0)
die(7, "%s", "Failed to connect stream socket\n");
I need my server to broadcast a message (not that it matters but it contains its IP/port info). What I have currently is the working server broadcast, code below. I'm not sure about setting up the client because usually I would use the IP/port of the server which the client doesn't have until it receives the broadcast. The client never receives anything. Can someone tell me what is wrong.
Server:
struct sockaddr_in server, bcast;
int sockfd;
int blen = sizeof(bcast);
int svrlen = sizeof(server);
char buf[BUFLEN];
if((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
printf("Socket error.\n");
exit(1);
}
int broadcastPermission = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (void *)&broadcastPermission,sizeof(broadcastPermission)) < 0){
printf("Error setting socket options.");
}
memset(&bcast, 0, sizeof(bcast));
bcast.sin_family = AF_INET;
bcast.sin_port = htons(PORT);
bcast.sin_addr.s_addr = htonl(INADDR_ANY);
string bcastIP = BCASTIP;
if(inet_aton("255.255.255.255", &bcast.sin_addr) == 0){
printf("Broadcast Address error.");
exit(1);
}
if (bind(sockfd, (struct sockaddr*)&server, sizeof(server)) == -1){
printf("Port error.\n");
exit(1);
}
fflush(stdout);
if(int bytes = sendto(sockfd, ipinfo, sizeof(ipinfo), 0, (struct sockaddr*)&bcast, blen) == -1){
printf("Broadcast send error.");
}
else{
printf("Sent"):
}
Client:
struct sockaddr_in server;
int sockfd;
int bytes;
int svrlen = sizeof(server);
char buf[BUFLEN]
if((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
printf("Socket error.\n");
exit(1);
}
memset((char *)&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(BPORT);
server.sin_addr.s_addr = htonl(INADDR_ANY);
while(1){
printf("Waiting for broadcast...\n\n");
fflush(stdout);
memset(buf,0,BUFLEN);
bytes = recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&server, (socklen_t*)&svrlen);
printf("Received");
}
Your client is not calling bind() on the socket before trying to receive data.
http://cs.baylor.edu/~donahoo/practical/CSockets/code/BroadcastReceiver.c shows the following example which you may find helpful:
void DieWithError(char *errorMessage); /* External error handling function */
int main(int argc, char *argv[])
{
int sock; /* Socket */
struct sockaddr_in broadcastAddr; /* Broadcast Address */
unsigned short broadcastPort; /* Port */
char recvString[MAXRECVSTRING+1]; /* Buffer for received string */
int recvStringLen; /* Length of received string */
if (argc != 2) /* Test for correct number of arguments */
{
fprintf(stderr,"Usage: %s <Broadcast Port>\n", argv[0]);
exit(1);
}
broadcastPort = atoi(argv[1]); /* First arg: broadcast port */
/* Create a best-effort datagram socket using UDP */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Construct bind structure */
memset(&broadcastAddr, 0, sizeof(broadcastAddr)); /* Zero out structure */
broadcastAddr.sin_family = AF_INET; /* Internet address family */
broadcastAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
broadcastAddr.sin_port = htons(broadcastPort); /* Broadcast port */
/* Bind to the broadcast port */
if (bind(sock, (struct sockaddr *) &broadcastAddr, sizeof(broadcastAddr)) < 0)
DieWithError("bind() failed");
/* Receive a single datagram from the server */
if ((recvStringLen = recvfrom(sock, recvString, MAXRECVSTRING, 0, NULL, 0)) < 0)
DieWithError("recvfrom() failed");
recvString[recvStringLen] = '\0';
printf("Received: %s\n", recvString); /* Print the received string */
close(sock);
exit(0);
}
I need my server to broadcast a message (not that it matters but it contains its IP/port info).
That sounds a lot like service discovery. You should really use the standard mDNS/Zeroconf protocol for that. You can use the Avahi library for that (or use the Avahi service on Linux or Zeroconf on MacOS X).
This is my code
#include "basic.h"
#include "bp_socket.h"
int setup_tcp(char *port)
{
struct sockaddr_in server_addr;
in_port_t server_port;
int sock;
int retval; //return value
if ((server_port = atoi(port)) < 0)
{
server_port = (in_port_t)DEFAULT_PORT;
fprintf(stderr, "Error port: %d in line %d\n", (int)server_port, __LINE__);
//fprintf(stderr, "Use default port: %d\n", DEFAULT_PORT);
}
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0)
{
return sock;
}
retval = listen(sock, 40);
if (retval < 0)
{
return retval;
}
memset(&server_addr, 0, sizeof(struct sockaddr_in));
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(server_port);
server_addr.sin_family = AF_INET;
retval = bind(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (retval < 0)
{
perror("bind");
return retval;
}
return sock;
}
int main()
{
printf("%d\n", setup_tcp("4558"));
perror("");
return 0;
}
I debug my code, then I found bind() return -1
I google it and read man page, but I couldn't found my answer.
function setup_tcp is create socket, and bind with address.
then return a socket or errno value.
How to solve it. I had read my code for many times.
Thank you!
You should move the listen after the bind.
bind returns an error if the socket is already bound, and listen on an unbound socket automatically binds it to a random port number.
My application is running on CentOS 5.5.
I'm using raw socket to send data:
sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (sd < 0) {
// Error
}
const int opt_on = 1;
rc = setsockopt(m_SocketDescriptor, IPPROTO_IP, IP_HDRINCL, &opt_on, sizeof(opt_on));
if (rc < 0) {
close(sd);
// Error
}
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = my_ip_address;
if (sendto(m_SocketDescriptor, DataBuffer, (size_t)TotalSize, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0) {
close(sd);
// Error
}
How can I bind this socket to specific network interface (say eth1)?
const char *opt;
opt = "eth0";
const len = strnlen(opt, IFNAMSIZ);
if (len == IFNAMSIZ) {
fprintf(stderr, "Too long iface name");
return 1;
}
setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, opt, len);
First line: set up your variable
Second line: tell the program which interface to bind to
Lines 3-5: get length of interface name and check if it's size not too big.
Six line: set the socket options for socket sd, binding to the device opt.
setsockopt prototype:
int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);
Also, make sure you include the if.h, socket.h and string.h header files
As mentioned earlier, the correct thing to do is use the struct ifreq to specify the interface name. Here is my code sample.
#define SERVERPORT 5555
...
struct ifreq ifr;
/* Create the socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd < 0)
{
printf("Error in socket() creation - %s", strerror(errno));
}
/* Bind to eth1 interface only - this is a private VLAN */
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth1");
if ((rc = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr))) < 0)
{
perror("Server-setsockopt() error for SO_BINDTODEVICE");
printf("%s\n", strerror(errno));
close(sd);
exit(-1);
}
/* bind to an address */
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVERPORT);
serveraddr.sin_addr.s_addr = inet_addr("9.1.2.3");
int rc = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
I would also like to add that from a security perspective, while it is good to bind the socket to an interface, it does not make sense to use INADDR_ANY as the listening IP address. Doing so would make the port appear open in netstat on all network interfaces.
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 0.0.0.0:5555 0.0.0.0:* LISTEN 0 210898 26996/myserver
Instead, I specified an IP address specific to the interface being used (a private VLAN). This fixed the netstat output too:
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 9.1.2.3:5555 0.0.0.0:* LISTEN 0 210898 26996/myserver
Bind socket to specific interface IP address
int bind_using_iface_ip(int fd, char *ipaddr, uint16_t port)
{
struct sockaddr_in localaddr = {0};
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(port);
localaddr.sin_addr.s_addr = inet_addr(ipaddr);
return bind(fd, (struct sockaddr*) &localaddr, sizeof(struct sockaddr_in));
}
Bind socket to specific interface name
int bind_using_iface_name(int fd, char *iface_name)
{
return setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, iface_name, strlen(iface_name))
}
In bind_using_iface_ip, to bind to any port 0 should be passed. And also if the fd is raw socket then need to pass port as 0. This bind mechanism is common for all kind of sockets like raw, dgram and stream.