I'm just learning how to create servers in C and I keep getting a "segmentation fault: 11" error when i try telnetting into this server from another terminal. any help would be greatly appreciated!
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
void error(char *msg)
{
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(1);
}
int main(int argc, char *argv[])
{
char *advice[] = {
"Take smaller bites\r\n",
"Go for the tight jeans. No they do NOT make you look fat.\r\n",
"One word: inappropriate\r\n",
"Just for today, be honest. Tell your boss what you *really* think\r\n",
"You might want to rethink that haircut\r\n"
};
int listener_d = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in name;
name.sin_family = PF_INET;
name.sin_port = (in_port_t)htons(30000);
name.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(listener_d, (struct sockaddr *) &name, sizeof(name))== -1)
error("Cannot bind");
if (listen(listener_d, 10) == -1)
error("Cannot listen");
puts("Waiting connection");
while(1)
{
struct sockaddr_storage client_addr;
unsigned int address_size = sizeof(client_addr);
int connect_d = accept(listener_d, (struct sockaddr *) &client_addr, &address_size);
char msg = advice[0];
if (send(connect_d, msg, strlen(msg), 0) == -1)
error("Cannot send");
close(connect_d);
}
return 0;
}
You're storing advice[0] into a char rather than a char *. It won't fit, and is truncated, making the pointer invalid. Store it in a char * (or even const char *) instead.
I'd also recommend turning on warnings in your compiler, since they would have caught this mistake. For GCC and Clang, I use -Wall -Wextra -pedantic.
Related
I'd like to connect to a ssh server which has an ipv6 address with libssh2.
It works but when I give an ip that isn't the localhost it fails to connect.
The ip is correct because I can connect to it with ssh <ipv6> -p 22.
const char *ip = "::1";
struct sockaddr_storage storage;
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &storage;
addr6->sin6_family = AF_INET6;
addr6->sin6_port = htons(22);
int sock;
if(inet_pton(AF_INET6, ip, &addr6->sin6_addr) == 1)
{
if((sock = socket(AF_INET6, SOCK_STREAM, 0)) != -1)
{
if(connect(sock, (struct sockaddr *)(&storage),
sizeof(struct sockaddr_in6)) == 0)
{
printf("works\n");
}
close(sock);
}
}
Edit:
The suggestion (memset(&storage, 0, sizeof(storage))) by #idz seems to have resolved the problem.
Non-static structures in C are not zero-initialized, so to avoid the possibility of garbage in the memory causing errors, you should zero them out.
Adding:
memset(&storage, 0, sizeof(storage));
just after the storage declaration will do the trick.
While not directly related to the OP's error, it's always easier to find out what's going wrong if you do not throw away the error information available to you.
Exactly how you do this will depend on the environment you're coding in, but for a simple command line program you might do something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// https://stackoverflow.com/questions/70157711/cannot-connect-to-ipv6-address-if-its-not-1-in-c
int main(int argc, const char * argv[]) {
const char *ip = "::1";
struct sockaddr_storage storage;
memset(&storage, 0, sizeof(storage));
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &storage;
addr6->sin6_family = AF_INET6;
addr6->sin6_port = htons(22);
int result = inet_pton(AF_INET6, ip, &addr6->sin6_addr);
if (result != 1) {
perror("inet_pton");
exit(EXIT_FAILURE);
}
int sock = socket(AF_INET6, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
result = connect(sock, (struct sockaddr *)(&storage), sizeof(struct sockaddr_in6));
if (result != 0) {
perror("connect");
exit(EXIT_FAILURE);
}
printf("It worked...\n");
close(sock);
return EXIT_SUCCESS;
}
In the case of garbage in the address this would report:
connect: Invalid argument
whereas a network routing issue would result in:
connect: No route to host
This makes it much easier to figure out what is going on!
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm trying to make a simple client-server API to be used for two of my machines. I made this simple program that uses the functions I made to test it. For some reason my client sends a message just fine, but my server can't (however, it receives the message from the client).
Server side output:
host name: my_host
Our port number is: 34440
Client msg: Client msg
Send failed: Invalid argument
Message from Server sent to Client
Client side output:
Connection established with server...
Message from Client sent to Server
Server side:
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include "my_socket.h"
int main() {
server_init();
char *msg = "Server msg";
char buffer[100];
int n = read_from_client((char *)buffer);
buffer[n] = '\0';
printf("Client msg: %s\n", buffer);
write_to_client((char *)msg);
printf("Message from Server sent to Client \n");
return 0;
}
Client Side:
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include "my_socket.h"
int main() {
client_init();
char *msg = "Client msg";
char buffer[100];
write_to_server((char*)msg);
printf("Message from Client sent to Server \n");
int n = read_from_server((char *)buffer);
buffer[n] = '\0';
printf("Server msg: %s\n", buffer);
close_socket();
return 0;
}
my_socket.c:
#include "my_socket.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
int sockfd1;
int sockfd2;
int MAX_BUFF = 1024;
struct sockaddr_in server;
struct sockaddr_in client;
struct hostent *host;
ssize_t write_to_server(const void *buffer){
int bytes_sent, server_size = sizeof(server), buf_len = strlen(buffer);
if ((bytes_sent = sendto(sockfd2, buffer, buf_len, 0,
(const struct sockaddr *)&server, server_size)) < 0){
perror("Send failed");
}
return bytes_sent;
}
ssize_t write_to_client(const void *buffer){
int bytes_sent, client_size = sizeof(client), buf_len = strlen(buffer);
if ((bytes_sent = sendto(sockfd1, buffer, buf_len, 0,
(const struct sockaddr *)&client, client_size)) < 0){
perror("Send failed");
}
return bytes_sent;
}
int read_from_server(void *buffer){
int bytes_rcv, len;
if ((bytes_rcv = recvfrom(sockfd2, buffer, MAX_BUFF, MSG_WAITALL,
(struct sockaddr *)&server, &len)) < 0){
perror("Read failed");
}
return bytes_rcv;
}
int read_from_client(void *buffer){
int bytes_rcv, len;
if ((bytes_rcv = recvfrom(sockfd1, buffer, MAX_BUFF, MSG_WAITALL,
(struct sockaddr *)&client, &len)) < 0){
perror("Read failed");
}
return bytes_rcv;
}
void close_socket() {
close(sockfd1);
close(sockfd2);
}
void server_init(){
if ( (sockfd1 = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
}
char name[1024];
name[1023] = '\0';
gethostname(name, 1023);
printf("host name: %s \n", name);
host = gethostbyname("my_host");
if(host == NULL){
perror("Host is null");
exit(0);
}
bzero((char *)&server, sizeof(server));
bzero((char *)&client, sizeof(client));
server.sin_family = AF_INET;
bcopy((char *)host->h_addr,
(char *)&server.sin_addr.s_addr, host->h_length);
//server.sin_port = 0;
server.sin_port = htons(34440);
if ( (bind(sockfd1, (struct sockaddr *)&server, sizeof(server) ) ) < 0 ){
perror("bind failed");
}
socklen_t len = sizeof(server);
if (getsockname(sockfd1, (struct sockaddr *)&server, &len) == -1){
perror("getsockname");
}else{
printf("Our port number is: %d\n", ntohs(server.sin_port));
}
}
void client_init(){
if ( (sockfd2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
}
host = gethostbyname("my_host");
if(host == NULL){
perror("Host is null");
exit(0);
}
bzero((char *)&server, sizeof(server));
server.sin_family = AF_INET;
bcopy((char *)host->h_addr,
(char *)&server.sin_addr.s_addr, host->h_length);
//server.sin_port = 0;
server.sin_port = htons(34440);
if(connect(sockfd2, (struct sockaddr *)&server, sizeof(server)) == 0){
printf("Connection established with server...\n");
}
}
my_socket.h:
#ifndef MY_SOCKET
#define MY_SOCKET
#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>
#include <netdb.h>
extern int sockfd1;
extern int sockfd2;
extern int MAX_BUFF;
extern struct sockaddr_in server;
extern struct sockaddr_in client;
extern struct hostent *host;
// Send a message over the socket
ssize_t write_to_server(const void *buffer);
ssize_t write_to_client(const void *buffer);
// Blocks until told it's ready; receives bytes from socket
int read_from_server(void *buffer);
int read_from_client(void *buffer);
// Close the socket
void close_socket();
void server_init();
void client_init();
#endif
Any advice or criticism is welcome. Thanks in advance.
At least one issue is that you are not initializing the len variable in read_from_client. The manual page for recvfrom says, in part (emphasis added):
... addrlen is a value-result argument. Before the call, it should be initialized to the size of the buffer associated with src_addr. Upon return, addrlen is updated to contain the actual size of the source address. The returned address is truncated if the buffer provided is too small; in this case, addrlen will return a value greater than was supplied to the call.
That means that, as an uninitialized stack variable, len has an indeterminate value. Probably zero, but at least something smaller than sizeof(struct sockaddr_in). As a result, client is not getting filled in correctly by the recvfrom.
Just before the recvfrom, you should initialize it with:
len = sizeof(client);
On the client side, write_to_server and read_from_server need not use recvfrom and sendto as you have already done a connect on the socket. They can simply use recv and send since the remote socket endpoint is already established by the connect. I believe the address is simply ignored for a connected socket, but I cannot find where that is documented right now.
(In any case, if you do continue to use recvfrom on the client side, you should make the same len initialization there.)
I'm making a simple UDP daytime client. I'm getting this when I try to compile. I've tried casting these to see if they would work but that doesn't lead anywhere. How should I go about entering these parameters with what I have (or am I missing something that should be put there)?
UDPday2.cpp:57:86: error: invalid conversion from ‘int*’ to ‘socklen_t* {aka unsigned int*}’ [-fpermissive]
n = recvfrom(sockfd, buf,(int) sizeof(buf), 0, (sockaddr*)&serveraddr, &serverlen);
^
In file included from UDPday2.cpp:6:0:
/usr/include/i386-linux-gnu/sys/socket.h:174:16: error: initializing argument 6 of ‘ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*)’ [-fpermissive]
extern ssize_t recvfrom (int __fd, void *__restrict __buf, size_t __n,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define BUFSIZE 1024
void error(char *msg) {
perror(msg);
exit(0);
}
int main(int argc, char **argv) {
int sockfd, portno, n;
int serverlen;
struct sockaddr_in serveraddr;
struct hostent *server;
char *hostname;
char buf[BUFSIZE];
portno = 13;
if(argc == 1)
hostname = "localhost";
else
hostname = argv[1];
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
error("socket");
server = gethostbyname(hostname);
if (server == NULL) {
fprintf(stderr," no host %s\n", hostname);
exit(0);
}
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serveraddr.sin_addr.s_addr, server->h_length);
serveraddr.sin_port = htons(portno);
serverlen = sizeof(serveraddr);
n = sendto(sockfd, buf,(int)strlen(buf)+1, 0,(sockaddr*)&serveraddr , serverlen);
if (n < 0)
error("ERROR send");
n = recvfrom(sockfd, buf,(int) sizeof(buf), 0, (sockaddr*)&serveraddr, &serverlen);
if (n < 0)
error("ERROR recvfrom");
printf(" %s", buf);
return 0;
}
serverlen needs to be declared as unsigned, or as a socklen_t. You should have been able to deduce that from the error message.
I'm either very tired and not noticing something simple , or this is completely screwing with me. I'm getting a segmentation fault ( core dumped ) and I've managed to pinpoint it to the sendto() in the worker function. (in the server)
Server code:
//UDPServer.c
/*
* gcc -o server UDPServer.c
* ./server <port> <buffersize>
*/
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
void err(char *str)
{
perror(str);
exit(1);
}
int sock;
typedef struct
{
struct sockaddr_in client;
int buffsize;
char *msg;
} data;
void *worker (void* asd)
{
int len;
FILE *fp;
data d;
d = *(data*) asd;
char buff[d.buffsize];
printf("Received packet from %s:%d\nData:%sSize:%d\n",
inet_ntoa(d.client.sin_addr), ntohs(d.client.sin_port)
,d.msg,d.buffsize);
char * fn;
memcpy (fn,d.msg,strlen(d.msg)-1);
fp = fopen(fn,"rb");
int bytes;
len = sizeof(d.client);
printf ("%d\n",len);
while (bytes=fread(buff,sizeof(char),d.buffsize,fp))
{
printf ("Server sent %d bytes.\n",bytes);
-> this if right here. this causes the core dump when attempting to send
if(sendto(sock , &buff , sizeof(buff),0,(struct sockaddr *)&d.client,len)<0)
err("Error sending.");
}
fclose(fp);
}
int main(int argc, char** argv)
{
struct sockaddr_in server, client;
int port, i;
socklen_t slen=sizeof(client);
if(argc != 3)
{
printf("Usage: <Port> <Bytes>\n");
exit(0);
}
else
sscanf(argv[1],"%d",&port);
int buffsize = atoi(argv[2]);
char buff[buffsize];
if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
err("socket");
else
printf("Server : Socket() successful\n");
bzero(&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (struct sockaddr* ) &server, sizeof(server))==-1)
err("bind");
else
printf("Server : bind() successful\n");
while(1)
{
memset(&buff,0,sizeof(buff));
if (recvfrom(sock, &buff, sizeof(buff), 0, (struct sockaddr*)&client, &slen)==-1)
err("recvfrom()");
data d;
d.client = client;
d.buffsize = buffsize;
d.msg = buff;
pthread_t t;
pthread_create(&t,NULL,worker,&d);
pthread_join(t,NULL);
}
return 0;
}
I don't think the client is relevant here since it's only job is to send the filename. The read works btw , I've tested.
Anyway , I'm just trying to send the content of the file for the moment.I've been trying to figure this out for the past hour and for the life of me I can't find out what's it's problem. The segmentation fault makes no sense to me.
Any suggestions are greatly appreciated.
I'd be nervous about the sizeof(buff) in the sendto. buff's size is fixed at runtime based on the argument. But sizeof is a compile-time operation. (Or at least it was back in the good old days - I'm not sure about C99) Oh, nevermind - I see that has changed
Still, why not use d.buffsize there instead? Or maybe bytes, since you might not have filled the buffer.
Although #21Zoo is wrong about dynamic arrays in C99, I think he found the root problem
char * fn;
memcpy (fn,d.msg,strlen(d.msg)-1);
fn has no memory allocated to copy into, so you are writing to a random point in memory.
Something in the sendto is probably stumbling over that memory which now contains garbage.
You either need to malloc(strlen(d.msg)+1) or use strdup instead.
This code is generating "Connection Failed error", (the error generating portion is commented below in the code) even when i am supplying the correct input format eg.
./Client ip text portno
./Client 127.0.0.1 "tushar" 7100
//AUTHOR: TUSHAR MAROO
//Client.c
//header files used
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
//constants
#define RCVBUFFERSIZE 32
//functions used
void DieWithError(char *errorMessage);
//main program
int main(int argc, char *argv[]){
int sock;
struct sockaddr_in serverAddr;
unsigned short serverPort;
char *serverIp;
char *message;
unsigned int messageLength;
char buffer[RCVBUFFERSIZE];
//condition check deplyed for nuber of arguements not for data in arguements
if((argc<3) || (argc>4)){
fprintf(stderr,"Format: %s <Server's IP> <Your Message> <Port Number>\n",argv[0]);
exit(1);
}
serverIp = argv[1];
message = argv[2];
if(argc == 4){
serverPort = atoi(argv[3]);
} else {
serverPort = 7;
}
//create a socket and check success and handle error
if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0 )
fprintf(stderr, "Socket Creation Fail");
//server details
//bzero((struct sockaddr_in *)(&serverAddr),sizeof(serverAddr));
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr(serverIp);
serverAddr.sin_port = htons(serverPort);
printf("tusharmaroo");
//not working why??
//if (connect(sock, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0)
//DieWithError("Connection Error..");
//fprintf(stderr,"Connection error");
//this snippet also not working
if (connect(sock, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0)
DieWithError("connect() failed");
printf("connected....");
messageLength = strlen(message);
if(send(sock, message, messageLength, 0) > 0)
printf("message sent....");
close(sock);
exit(0);
}
//AUTHOR TUSHAR MAROO
//SERVER CODE
//header files
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
//constants declared
#define ALLOWEDCONNECTIONS 5
//external functions
void DieWithError(char *error);
void ClientHandle(int sock);
//main code
int main(int argc, char argv[]){
int serverSock;
int clientSock;
struct sockaddr_in serverAddr;
struct sockaddr_in clientAddr;
unsigned int serverPort;
unsigned int clientLength;
if(argc != 2){
fprintf(stderr,"Format: %d <Port No.>", argv[0]);
//DieWithError("Pass Correct Number of Arguements...");
exit(1);
}
if((serverSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
DieWithError("Socket not Created");
exit(1);
}
serverPort = htons((argv[1]));
//assign address to the server
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr.sin_port = htons(serverPort);
//socket has been created now bind it to some ip and port
if((bind(serverSock,(struct sockaddr *)&serverAddr,sizeof(serverAddr))) < 0){
DieWithError("Binding Failed");
}
if(listen(serverSock,5) < 0){
DieWithError("Listen Failed");
}
for(;;){
clientLength = sizeof(clientAddr);
if((clientSock = accept(serverSock, (struct sockaddr *) &clientAddr, &clientLength)) < 0){
DieWithError("Accept() failed");
exit(1);
}
printf("Handling Client %s ",inet_ntoa(clientAddr.sin_addr));
}
return 0;
}
This is wrong in the server code
serverPort = htons((argv[1]));
This should be
serverPort = htons(atoi(argv[1]));
Are you sure there are no firewall rules causing troubles for you? Ensure that.
If the connect fails you should be able to print out the error using perror or strerror:
perror("Could not connect:");
works for me
client and server are ubuntu 12.04
for server, run in a shell
nc -l 9999
This is on a host with the address "192.168.56.13"
for client, compile code above with "DieWithError" fixed up
void DieWithError(char *errorMessage) { printf("%s",errorMessage); exit(1); }
cc -o foo foo.c
./foo 192.168.56.13 "hello" 9999</strike>
replace the DieWithError() with perror() Then I would guess that it will print out "connection refused" as you seem to have a networking problem with getting the server running on the correct address.
However, if the address in your client is correct the nc program WILL print "hello"
you just altered your program the previous version worked for me. The current version, I don't know if it does.
Like everyone else is saying, use perror() to get proper diagnostics