I'm trying to get started on socket programming in C, and I was following a few guides, but I'm always getting this error:
warning:
passing argument 2 of ‘connect’ from incompatible pointer type [-Wincompatible-pointer-types]
45 | int status= connect(socket_desc , (struct sockaddr *) &server , sizeof(server));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| struct sockaddr *
It wants struct sockaddr * to be constant, but when I try to make it constant, the connect() function doesn't have enough arguments.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main (){
int netsocket;
netsocket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(9002);
server.sin_addr.s_addr = INADDR_ANY;
int Verbindungsstatus = connect(netsocket, (struct sockaddr *) &server, sizeof(server));
if (Verbindungsstatus == -1){
printf("Connection error");
}
printf("Connected!");
return 0;
}
From the man page:
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
The second argument expects a const struct sockaddr *addr.
Perhaps try casting to (const struct sockaddr *) instead of (struct sockaddr *).
New code should use getaddrinfo() instead of manually filling the struct. See the man page for an example:
https://man7.org/linux/man-pages/man3/getaddrinfo.3.html
Aside: socket() may fail:
netsocket = socket(AF_INET, SOCK_STREAM, 0);
Check its return value.
errno = 0;
if ((netsocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
}
Related
I am trying to compile this C program but I am getting this message
warning: passing 'int *' to parameter of type 'socklen_t *'
(aka 'unsigned int *') converts between pointers to integer types with
different sign [-Wpointer-sign]
if ((new_s = accept(s, (struct sockaddr *) &sin, &addr_len)) < 0) {
^~~~~~~~~
someone could help me?
#include<string.h>
#include<stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h> // for open
#include <unistd.h> // for close
#define SERVER_PORT 5432
#define MAX_PENDING 5
#define MAX_LINE 256
int main()
{
struct sockaddr_in sin;
char buf[MAX_LINE];
int buf_len, addr_len;
int s, new_s;
/* 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);
/* setup passive open */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("simplex-talk: socket");
exit(1);
}
if ((bind(s, (struct sockaddr *)&sin, sizeof(sin))) < 0) {
perror("simplex-talk: bind");
exit(1);
}
listen(s, MAX_PENDING);
/* wait for connection, then receive and print text */
while(1) {
if ((new_s = accept(s, (struct sockaddr *) &sin, &addr_len)) < 0) {
perror("simplex-talk: accept");
exit(1);
}
while (buf_len == recv(new_s, buf, sizeof(buf), 0))
fputs(buf, stdout);
close(new_s);
}
}
As the error message states, you're passing an int * argument to accept for the last argument when the function expects a socklen_t * for this argument.
So change the type of addr_len to socklen_t.
I was writing a simple C code to create a lisening socket. The code is teh following:
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
void main() {
struct sockaddr_in server;
struct sockaddr_in client;
int clientlen;
char buf[1500];
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
memset((char *)&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(9090);
if(bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0)
error("ERROR on binding");
while(1) {
bzero(buf, 1500);
recvfrom(sock, buf, 1500-1, 0, (struct sockaddr *) &client, &clientlen);
printf("%s\n", buf);
printf("%d - %s\n", client.sin_port, client.sin_addr.s_addr);
}
close(sock);
}
The code compile with no problem but when I connect to the server with a client using netcat:
nc -u 10.0.2.4 9090
and I send some message, the message are replied and then I get the error. DO someone knows why I get this behaviour?
Thank you.
There are two main issues here. First, clientlen is expected to contain the size of the address structure before recvfrom is called, but it is uninitialized. So set it as follows:
int clientlen = sizeof(client);
Second, you're using %s to print client.sin_addr.s_addr but that field is not a string. You should use inet_ntoa to convert a struct inaddr_t to a string:
printf("%d - %s\n", ntohs(client.sin_port), inet_ntoa(client.sin_addr));
I have been at this for an ungodly amount of time, so I really hope someone can provide me some keen insight as to what is going on.
I have the following main function:
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char **argv) {
char *serv_IP;
in_port_t serv_port;
int sock;
struct sockaddr_in serv_addr;
serv_IP = argv[1];
serv_port = atoi(argv[2]);
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
fprintf(stderr, "Failed to create TCP socket\r\n");
exit(1);
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
if (inet_pton(AF_INET, serv_IP, &serv_addr.sin_addr.s_addr) == 0) {
fprintf(stderr, "Invalid IP address\r\n");
exit(1);
}
serv_addr.sin_port = htons(serv_port);
if (connect(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
fprintf(stderr, "Failed to connect to serv\r\n");
exit(1);
}
else {
printf("You're connected!\n);
}
close(sock)
return 0;
}
Now, this code works just fine. However, what I want to do is to replace the call to connect() with a helper function call to something like this:
void function(int sock, struct sockaddr_in *serv_addr) {
if (connect(sock, (struct sockaddr *) serv_addr, sizeof(serv_addr)) < 0) {
printf("Server IP = %s\n", inet_ntoa(serv_addr->sin_addr));
printf("Server port = %d\n", ntohs(serv_addr->sin_port));
fprintf(stderr, "Failed to connect to server\r\n");
exit(1);
}
else {
// Do other stuff
}
}
I remove the call to connect() from main() and replace it with the function call:
function(sock, &serv_addr);
As soon as the function is called, the correct IP and port numbers are printed out, but I still fail to connect to my server. The only difference is, in my main function(), I preface serv_addr in the connect call with the & - i.e., connect(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) - to reference its address, and I don't do that in the helper function because the address of serv_addr is already being passed as an argument - i.e., connect(sock, (struct sockaddr *) serv_addr, sizeof(serv_addr)). It makes no difference if I add the &, just in case you were wondering.
So, with the &serv_addr being passed to function() seemingly correctly, as verified by me being able to print out the correct IP and port numbers, why is it that I can connect in main() but not when I pass the serv_addr struct as an argument to another function and call connect() from there?
Thanks in advance for any help!
sizeof(serv_addr) returns 16 when serv_addr is declared as sockaddr_in, but returns 4 (in 32bit) or 8 (in 64bit) when declared as sockaddr_in*. It is too small either way, AF_INET needs 16. Had you looked at errno when connect() failed, it would have told you that you were passing an invalid parameter value.
You need to use sizeof(sockaddr_in), either directly:
void function(int sock, struct sockaddr_in *serv_addr)
{
if (connect(sock, (struct sockaddr *) serv_addr, sizeof(struct sockaddr_in)) < 0)
Or indirectly via sizeof(*serv_addr):
void function(int sock, struct sockaddr_in *serv_addr)
{
if (connect(sock, (struct sockaddr *) serv_addr, sizeof(*serv_addr)) < 0)
That did it! Thank you very much for your quick response!! I never would have thought about the return of sizeof() as a potential problem with returning different sizes for actual values vs. pointers to values. Totally makes sense, though. And I just read about the errno.h header as well as how to use it.
The exact line that fixed it was:
if (connect(sock, (struct sockaddr *) serv_addr, sizeof(struct sockaddr_in)) < 0)
I was right about not needing the '&' in front of serv_add. You also need the "struct" in sizeof() or else it returns sockaddr_in as an undeclared variable.
Anyways, thanks again.
Now I can finally move on with my code.
I would like to make program so that, when client disconnected, the server will back ready to accept a new request from client. Here is the code
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define MAXLINE 100
#define LISTENQ 10
int main()
{
int tmp, listenfd, connfd;
int sin_size;
struct sockaddr_in servaddr, cliaddr;
char buff[MAXLINE];
time_t ticks;
while(true)
{
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(13);
memset(&(servaddr.sin_zero),'\0',8);
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if(listenfd == -1){
perror("error socket");
exit(1);
}
tmp=bind(listenfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr));
if(tmp == -1){
perror("error bind..");
exit(1);
}
tmp=listen(listenfd, LISTENQ);
if(tmp == -1){
perror("error listen");
exit(1);
}
sin_size = sizeof(struct sockaddr_in);
connfd=accept(listenfd,(struct sockaddr *)&cliaddr, &sin_size);
if(connfd == -1){
perror("error accept");
exit(1);
}
ticks = time(NULL);
snprintf(buff,sizeof(buff),"Now Time: %.24s\r\n", ctime(&ticks));
write(connfd, buff, strlen(buff));
close(connfd);
close(listenfd);
}
}
I found a problem on this part
tmp=bind(listenfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr));
error: invalid conversion from 'int*' to 'socklen_t* {aka unsigned int*}' [-fpermissive]
connfd=accept(listenfd,(struct sockaddr *)&cliaddr, &sin_size);
error: initializing argument 3 of 'int accept(int, sockaddr*, socklen_t*)' [-fpermissive]
What should I do with those problem? Didn't the pointer right?
You need to use
socklen_t sin_size;
Chnage your declaration
socklen_t sin_size;
This solves your issue.
you can also Try this as last resort but above change would works fine for you.
Modify this statement
connfd=accept(listenfd,(struct sockaddr *)&cliaddr,(socklen_t * ) &sin_size);
See man accept
After seeing #alk comment i am adding this part from comment.
Especially when casting pointers, it might just cast away an compile-time error but very well might crash when running as the sizes of what the program expects when Dereferencing the pointer differs from reality.
Use while(1) instead of while(true) and use a C-compiler instead of a C++-compiler.
The errors come from compiling the source code with a C++compiler. If you use a C-Compiler your code does not produce the mentioned errors, except that now true is not defined.
Correct answer, need to run on root-access user
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#define MAXLINE 100
#define LISTENQ 10
int main()
{
int tmp, listenfd, connfd;
socklen_t sin_size;
struct sockaddr_in servaddr, cliaddr;
char buff[MAXLINE];
time_t ticks;
while(true)
{
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(13);
memset(&(servaddr.sin_zero),'\0',8);
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if(listenfd == -1){
perror("error socket");
exit(1);
}
tmp=bind(listenfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr));
if(tmp == -1){
perror("error bind..");
exit(1);
}
tmp=listen(listenfd, LISTENQ);
if(tmp == -1){
perror("error listen");
exit(1);
}
sin_size = sizeof(struct sockaddr_in);
connfd=accept(listenfd,(struct sockaddr *)&cliaddr, &sin_size);
if(connfd == -1){
perror("error accept");
exit(1);
}
ticks = time(NULL);
snprintf(buff,sizeof(buff),"Sekarang pukul: %.24s\r\n", ctime(&ticks));
write(connfd, buff, strlen(buff));
close(connfd);
close(listenfd);
}
}
I was trying to make the simple server code work:
/*
NAME: udpServer0
SYNOPSIS: udpServer0
DESCRIPTION: The program creates a datagram socket in the inet
domain, binds it to port 12345 and receives any message
arrived to the socket and prints it out
*/
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
int main(void)
{
int sd;
struct sockaddr_in server;
char buf[512];
int rc;
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(12345);
sd = socket (AF_INET,SOCK_DGRAM,0);
bind( sd, (SA *) &server, sizeof(server));
for(;;){
rc=recv (sd, buf, sizeof(buf), 0);
buf[rc]= (char) NULL;
printf("Received: %s\n", buf);
}
}
I got these error:
clang udp_server.c
udp_server.c:27:16: error: use of undeclared identifier 'SA'
bind( sd, (SA *) &server, sizeof(server));
^
udp_server.c:27:20: error: expected expression
bind( sd, (SA *) &server, sizeof(server));
^
2 errors generated.
Do I need to require some header to avoid this problem?
As the comments say you want: (struct sockaddr *) instead of (SA *).
SA must have been a typedef. If you want the best guide to socket programming see this: http://beej.us/guide/bgnet/output/html/multipage/index.html