I'm new to c and I am trying to learn the sockets api, but I got this error: Socket operation on non-socket from Bind
Socket did not give an error
daytimeserv1.c:
#include "../holds/runp.h"
#include "../holds/wrapper.h"
int main(int argc, char **argv) {
int listenfd, connfd;
struct sockaddr_in servaddr;
char buff[MAXLINE];
time_t ticks;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
memset(&listenfd, 0, sizeof(listenfd));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(13);
Bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
for( ; ; ) {
connfd = Accept(listenfd, (struct sockaddr *) NULL, NULL);
ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
Write(connfd, buff, strlen(buff));
Close(connfd);
}
}
Wrappers wrapper.c
#include "wrapper.h"
void err_sys(const char* x) {
perror(x);
exit(1);
}
int Socket(int family, int type, int protocol) {
int n = socket(family, type, protocol);
if (n < 0)
err_sys("socket error");
return(n);
}
void Bind(int fd, const struct sockaddr *sa, socklen_t salen) {
if(bind(fd, sa, salen) < 0)
err_sys("bind error");
}
runp.h is just includes and constants
Any help is much appreciated! Thanks!
(My build system is bazel if that helps at all)
You are erasing the socket handle you just created via
memset(&listenfd, 0, sizeof(listenfd));
so you should remove it.
I guess what you actualy wanted to do is
memset(&servaddr, 0, sizeof(servaddr));
Related
I have two programs: client and server. They're trying to find themselves in local network using broadcast.
Client sends simple packet on broadcast with SERVER_PORT (known before) and server prints info about connection, but when i tried this solution I found some strange behavaiour, when I uncomment last two lines of server.c server prints (one custom struct)
Connection from: 0.0.0.0 on port: 0
after commenting those lines everything works properly, am I missing something?
server.c
int broadcast_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in broadcast_addr;
broadcast_addr.sin_addr.s_addr = INADDR_ANY;
broadcast_addr.sin_port = htons(SERVER_PORT);
broadcast_addr.sin_family = AF_INET;
if (bind(broadcast_socket, (struct sockaddr *)&broadcast_addr,
sizeof(broadcast_addr))) {
perror("bind");
}
struct sockaddr_in recv_addr;
char buf[MAX_PACKET_SIZE];
socklen_t len;
if (recvfrom(broadcast_socket, buf, MAX_PACKET_SIZE, 0,
(struct sockaddr *)&recv_addr, &len) < 0) {
perror("recvfrom");
}
printf("Connection from: %s on port: %d\nMessage: %s\n",
inet_ntoa(recv_addr.sin_addr), ntohs(recv_addr.sin_port), buf);
/* struct network_packet packet; */
/* struct sockaddr_in my_addr; */
client.c
int find_server(struct sockaddr_in *out) {
struct sockaddr_in broadcast;
struct network_packet packet;
int yes = 1;
socklen_t len;
broadcast.sin_addr.s_addr = INADDR_ANY;
broadcast.sin_port = htons(CLIENT_PORT);
broadcast.sin_family = AF_INET;
int socket_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (bind(socket_fd, (struct sockaddr *)&broadcast, sizeof(broadcast))) {
perror("bind");
}
if (get_broadcast_addr(&broadcast.sin_addr)) {
return -1;
}
printf("Target address: %s\n", inet_ntoa(broadcast.sin_addr));
broadcast.sin_port = htons(SERVER_PORT);
broadcast.sin_family = AF_INET;
setsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));
char buf[10] = "test";
sendto(socket_fd, buf, strlen(buf), 0, (struct sockaddr *)&broadcast,
sizeof(broadcast));
if (recvfrom(socket_fd, &packet, sizeof(packet), 0,
(struct sockaddr *)&broadcast, &len) < 0) {
perror("recvfrom");
}
struct sockaddr_in *sa = (struct sockaddr_in *)packet.data;
memcpy(out, sa, packet.header.packet_length);
return 0;
}
struct network_packet_header {
enum network_packet_type type;
int packet_length;
};
struct network_packet {
struct network_packet_header header;
unsigned char data[MAX_DATA_LENGTH];
};
You have to initialize the variable you pass as recvfrom's addrlen to the size of the address struct.
I have the UDPServer program running on linux and UDPClient program running on windows 10.
Note: In the UDP client program you have to add the linux server IP in the hash define.
Compilation on windows: gcc -Wall -o UDPClient UDPClient.c -lws2_32
Problem
UDPServer receives msg from UDP client and replies back. But the UDPClient on windows doesnt receive the msg from windows.
UDPServer.c (on linux)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 6200
#define MAXLINE 1024
int main() {
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from server";
struct sockaddr_in servaddr, cliaddr;
int n;
socklen_t from_len = sizeof(struct sockaddr);
socklen_t to_len = sizeof(struct sockaddr);
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));
// Filling server information
servaddr.sin_family = AF_INET; // IPv4
//servaddr.sin_addr.s_addr = inet_addr(IP_ADDR); ;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
// Bind the socket with the server address
if ( bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
n = recvfrom(sockfd, (char *)buffer, MAXLINE, 0, ( struct sockaddr *) &cliaddr, &from_len);
buffer[n] = '\0';
printf("Client : %s ; IP = %s ; Port = %d\n", buffer,inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
sendto(sockfd, (const char *)hello, strlen(hello), MSG_CONFIRM, (const struct sockaddr *) &cliaddr, to_len);
printf("Hello message sent.\n");
return 0;
}
// UDP client (on windows)
#include<stdio.h>
#include<winsock2.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#define PORT 6200
#define IP_ADDR "xx.xx.xx.xx" //Add the linux server IP
#define BUF_SIZE 1024
/* Compilation: gcc -Wall -o UDPClient UDPClient.c -lws2_32 */
int SetupWinSock()
{
WSADATA wsa;
//printf("SetupWinSock: Initializing socket system\n");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("SetupWinSock: Failed. Error Code : %d",WSAGetLastError());
return -1;
}
//printf("SetupWinSock: Initialization complete\n");
return 0;
}
SOCKET CreateUDPSocket()
{
SOCKET udpSocket;
if((udpSocket = socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP )) == INVALID_SOCKET)
{
printf("CreateUDPSocket: Failed to create socket : %d" , WSAGetLastError());
return -1;
}
else
{
//printf("CreateUDPSocket: Socket creation successful\n");
}
return udpSocket;
}
int main() {
char buffer[BUF_SIZE];
char *hello = "Hello from client";
struct sockaddr_in servaddr, localAddr;
SOCKET udpSocket;
int n, len;
SetupWinSock();
// Creating socket file descriptor
udpSocket = CreateUDPSocket();
memset(&servaddr, 0, sizeof(servaddr));
// Server info
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = inet_addr(IP_ADDR);
// Client info
localAddr.sin_family = AF_INET;
localAddr.sin_port = htons(PORT);
localAddr.sin_addr.s_addr = INADDR_ANY;
if ( bind(udpSocket,(const struct sockaddr *)&localAddr, sizeof(localAddr)) < 0 )
{
printf("Failed to bind\n");
return -1;
}
sendto(udpSocket, (const char *)hello, strlen(hello), 0, (const struct sockaddr *) &servaddr, sizeof(servaddr));
printf("Hello message sent.\n");
n = recvfrom(udpSocket, (char *)buffer, BUF_SIZE, 0, (struct sockaddr *) &servaddr, &len);
buffer[n] = '\0';
printf("Server : %s\n", buffer);
fflush(stdout);
closesocket(udpSocket);
WSACleanup();
while(1);
return 0;
}
there are two simple program to demo the unix domain DGRAM socket.
/* server */
int main(int ac, char *av[])
{
char buf[10];
int mpLogFD, len;
struct sockaddr_un serverAddress;
if((mpLogFD = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)
mpExit("sock");
unlink(MPLOGD_SOCK);
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sun_family = AF_LOCAL;
strcpy(serverAddress.sun_path, "/var/run/lsvr.sock");
if(bind(mpLogFD, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) < 0)
mpExit("bind");
perror("svr");
for(;;){
if(recvfrom(mpLogFD, buf, sizeof(buf), 0, (struct sockaddr *)&serverAddress, &len) < 0)
mpExit("recv");
printf("%s\n", buf);
}
}
/* client */
int main(int ac, char *av[])
{
int CliFD, len;
char buf[10];
struct sockaddr_un cliaddr;
if((CliFD = socket(AF_LOCAL, SOCK_DGRAM, 0)) == -1)
mpExit("cli sock");
memset(&cliaddr, 0, sizeof(cliaddr));
cliaddr.sun_family = AF_LOCAL;
strcpy(cliaddr.sun_path, "/var/run/lcli.sock");
if(bind(CliFD, (struct sockaddr *)&cliaddr, sizeof(cliaddr)))
mpExit("cli bind");
len = sizeof(cliaddr);
sprintf(buf, "12345678\n");
if(sendto(CliFD, buf, sizeof(buf), 0, (struct sockaddr *)&cliaddr, len) < 0)
mpExit("cli send");
perror("cli");
}
and the following is the result:
[root#jyl opt]# ./logsvr &
2033
svr: Success
[root#jyl opt]# ./logcli
cli: Success
[root#jyl opt]#
it seems like nothing wrong here. but, I get nothing from the server.
I don't know why it can't run as I expect.
You should be sending to /var/run/lsvr.sock not to /var/run/lcli.sock.
Also you don't have to bind in client so comment it out from client:
/* if(bind(CliFD, (struct sockaddr *)&cliaddr, sizeof(cliaddr)))
mpExit("cli bind");*/
I am starting to use aio to write a simple client server program.My client program:
int main(int argc, char const *argv[])
{
int port = 6000;
struct sockaddr_in my_address;
memset(&my_address, 0, sizeof(my_address));
my_address.sin_family = AF_INET;
my_address.sin_addr.s_addr = htonl(0x7f000001); // 127.0.0.1
my_address.sin_port = htons(port);
int fd = socket(AF_INET, SOCK_STREAM, 0);
connect(fd, (struct sockaddr*)&my_address, sizeof(my_address));
char * str = "hello";
struct aiocb my_aio;
memset((void*)&my_aio, 0, sizeof(struct aiocb));
my_aio.aio_fildes = fd;
my_aio.aio_buf = str;
my_aio.aio_nbytes = strlen(str);
aio_write(&my_aio);
return 0;
}
My server program:
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
sleep(5);
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
return 0;
}
I expect my server side to print out hello, but it does not. Thanks in advance.
Your code works otherwise, but your main is exited before the asynchronous write has completed; thus the socket is closed before the completion of asynchronous write. I did as little as add a perror("aio_write") after the aio_write call to find out what error it was giving if any, and now hello was successfully sent to the server.
You'd probably want to use aio_suspend to ensure that any outstanding operations are completed before exiting the main.
This is a simple iterative client-server program. Where the server prints out "Received request" on successful establishment of connection.
server side
#define LENGTH 256
#define SERV_PORT 4000
#define LISTENQ 8
int main()
{
int listenfd, connfd, n;
socklen_t clilen;
char buf[LENGTH];
struct sockaddr_in cliaddr, servaddr;
//creation of socket
listenfd = socket (AF_INET, SOCK_STREAM, 0);
//creating socket address
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
bind (listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
// printf("\nServer running.. waiting for connections");
// listen(listenfd, LISTENQ);
for(; ;)
{
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);
printf("\nReceived request");
//sleep(5);
}
return 0;
}
client side
#define LENGTH 256
#define SERV_PORT 4000
int main( int argc, char *argv[])
{
int sock;
struct sockaddr_in server;
struct hostent *hp;
char buff[256];
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
perror("socket failed");
exit(1);
}
server.sin_family = AF_INET;
hp = gethostbyname(argv[1]);
if(hp == 0)
{
perror("gethost by name failed");
exit(1);
}
memcpy(&server.sin_addr, hp->h_addr, hp->h_length);
server.sin_port = htons(4000);
if(connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0)
{
perror("\nconnect failed");
exit(1);
}
return 0;
}
When I run this multiple client-server code, the output for first client is different from the preceding clients. I need the first client to output like others. Can someone help?
When the first client establishes a connection with the server, the server doesn't output "Received request", where as, for the other clients do output "Received request".
You need to restore the listen() call. – EJP