I'm trying make IPv6 server, but i have issue with socket binding.
"could not bind socket"
All code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdbool.h>
int main(int argc, char *argv[]) {
int server_port = 8877;
struct sockaddr_in6 server_address;
memset(&server_address, 0, sizeof(server_address));
server_address.sin6_family = AF_INET6;
server_address.sin6_port = htons(server_port);
server_address.sin6_addr = in6addr_any;
int sockfd;
if (sockfd = socket(AF_INET6, SOCK_STREAM, 0) < 0) {
printf("could not create listen socket\n");
return 1;
}
if (bind(sockfd, (struct sockaddr *)&server_address, sizeof(server_address)) < 0) {
printf("could not bind socket\n");
return 1;
}
int numberOfClients = 1;
if (listen(sockfd, numberOfClients) < 0) {
printf("could not open socket for listening\n");
return 1;
}
struct sockaddr_in client_address;
int client_len = 0;
char buff4[INET_ADDRSTRLEN];
while (1) {
int sock;
if ((sock =
accept(sock, (struct sockaddr *)&client_address,
0)) < 0) {
printf("could not open a socket to accept data\n");
return 1;
}
//printf("client connected with ip address: %s\n", inet_ntop(AF_INET, &(client_address.sin_addr), buff4, INET_ADDRSTRLEN));
int n = 0;
int len = 0, maxlen = 100;
char buffer[maxlen];
char *pbuffer = buffer;
printf("client connected with ip address: %s\n",
inet_ntoa(client_address.sin_addr));
while ((n = recv(sock, pbuffer, maxlen, 0)) > 0) {
pbuffer += n;
maxlen -= n;
len += n;
printf("received: '%s'\n", buffer);
// echo received content back
send(sock, buffer, len, 0);
}
close(sock);
}
close(sockfd);
return 0;
}
The problem here is your order of operations.
You have written:
if (sockfd = socket(AF_INET6, SOCK_STREAM, 0) < 0) {
You expected this to assign the return value of socket() to sockfd. But instead, it compares that return value to 0, and whether that value is less than 0 is what is actually stored in sockfd.
Before comparing, you should use an extra pair of parentheses to make explicit that you want to do the assignment and only then do the comparison:
if ((sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
Better yet, make the code more maintainable by making it more obvious what is going on, by assigning first and then comparing separately.
sockfd = socket(AF_INET6, SOCK_STREAM, 0);
if (sockfd < 0) {
Related
It's been an hour since I started looking for THE error. I just started C sockets. The program exits with code -1 after printing "Error 1 connection error". The server in online, it's a netcat server. Where did I messed up ?
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#define HOST "127.0.0.1"
#define PORT 4444
int main(int argc, const char *argv[])
{
struct sockaddr_in addr;
int sock = 0;
int ret;
struct sockaddr_in server_addr;
char *msg = "Hello world !\n";
char inBuffer[1024] = { 0 };
if (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) < 0)
{
printf("Error %d socket creating.\n", sock);
exit(-1);
}
else
{
memset(&server_addr, '0', sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
if (ret = inet_pton(AF_INET, HOST, &server_addr.sin_addr) <= 0)
{
printf("Error %d unsuported address: %d\n", ret);
exit(-2);
}
else
{
if (ret = connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
printf("Error %d connection error\n", ret);
exit(-3);
}
else
{
send(sock, msg, strlen(msg), 0);
read(sock, inBuffer, 1024);
printf("%s\n", inBuffer);
return 0;
}
}
}
}
Due to operator precedence, the expression
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) < 0
is actually equal to
sock = (socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) < 0)
That is, you assign the result of the comparison socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) < 0 to the variable sock. The result of that comparison will always be either 0 (for false) or 1 (for true). Neither 0 nor 1 should be a valid socket.
You need to explicitly add parentheses for the assignment:
(sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0
The same needs to be done for the connect call and the comparison there.
I have a server that acknowledges a command and then sends data. It works fine with the command line: echo "show version" | nc -q1 127.0.0.1 5000 gives:
Command received: show version
Beta
I have a client that should behave exactly the same as the command line test, but it hangs on the second read() call unless I run it on a different server. I've had the same issue with unix domain sockets, except that they occasionally work.
Why would it fail only on localhost?
Client Source
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define ERR_FAIL_CONNECT -1
#define ERR_SOCK_SELECT -2
#define ERR_SOCK_READ -3
#define ERR_SOCK_WRITE -3
#define ERR_SOCK_REMOTE_CLOSED -4
int tcpConnect (char *ipAddr, int port);
int sendCommand (char *buf, int bufSize);
int readWithTimeout (int sock, char *buf, int bufSize, struct timeval *timeout);
int main() {
char buf[64];
int nBytes;
strcpy(buf, "show version");
nBytes = sendCommand(buf, sizeof(buf));
printf("Response: %s\n", buf);
return 0;
}
int sendCommand (char *buf, int bufSize) {
int apiSock;
int nBytes = ERR_SOCK_SELECT;
int len;
struct timeval timeout;
apiSock = tcpConnect("127.0.0.1", 5000);
if (!apiSock) return ERR_FAIL_CONNECT;
len = strlen(buf);
nBytes = write(apiSock, buf, len);
if (nBytes < 0) {
perror("ERROR writing to socket");
nBytes = ERR_SOCK_WRITE;
}
else if (nBytes < len) {
fprintf(stderr, "Command truncated at %d/%d\n", nBytes, len);
nBytes = ERR_SOCK_WRITE;
}
else {
timeout.tv_sec = 3;
timeout.tv_usec = 0;
nBytes = readWithTimeout(apiSock, buf, bufSize, &timeout);
if (nBytes > 0) {
timeout.tv_sec = 20;
timeout.tv_usec = 0;
nBytes = readWithTimeout(apiSock, buf, bufSize, &timeout);
}
}
close(apiSock);
return nBytes;
}
int tcpConnect (char *ipAddr, int port) {
struct sockaddr_in addr;
int sock;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
perror("ERROR: Could not create TCP socket");
return 0;
}
addr.sin_addr.s_addr = inet_addr(ipAddr);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("ERROR: Could not connect");
return 0;
}
return sock;
}
int readWithTimeout (int sock, char *buf, int bufSize, struct timeval *timeout) {
int res;
int nBytes = ERR_SOCK_SELECT;
fd_set set;
fprintf(stderr, "readWithTimeout(sock=%d, buf='%s', bufSize=%d, timeout{tv_sec=%d, tv_usec=%d})\n",
sock, buf, bufSize, timeout->tv_sec, timeout->tv_usec);
FD_ZERO(&set);
FD_SET(sock, &set);
res = select(sock+1, &set, NULL, NULL, timeout);
if (res < 0) perror("ERROR waiting for data");
else if (res == 0) fprintf(stderr, "Timed out waiting for data\n");
else {
nBytes = read(sock, buf, bufSize);
if (nBytes < 0) {
perror("ERROR reading from socket");
nBytes = ERR_SOCK_READ;
}
else if (nBytes == 0) {
fprintf(stderr, "Remote end closed socket\n");
shutdown(sock, 2);
close(sock);
nBytes = ERR_SOCK_REMOTE_CLOSED;
}
}
return nBytes;
}
Server Source
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define TCP_PORT 5000
#define BUF_SIZE 512
int readCommand(int clientSockFd);
void myWrite (int fileDescriptor, const void *buf, size_t nbytes);
int main (void) {
socklen_t client_len;
int optval;
int flags;
struct sockaddr_in serv_addr, client_addr;
int serverSockFd;
int clientSockFd;
fd_set set;
struct timeval timeout;
int rv;
serverSockFd = socket(AF_INET, SOCK_STREAM, 0);
if(serverSockFd < 0) perror("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(TCP_PORT);
if(bind(serverSockFd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("Unable to bind TCP socket");
}
listen(serverSockFd, 5);
client_len = sizeof(client_addr);
flags = fcntl(serverSockFd, F_GETFL, 0);
if (flags < 0) perror("Unable to read TCP socket flags");
flags = flags|O_NONBLOCK;
fcntl(serverSockFd, F_SETFL, flags);
// Wait for client connections
while(1) {
clientSockFd = accept(serverSockFd, (struct sockaddr *) &client_addr, &client_len);
if(clientSockFd < 0) {
usleep(50000);
continue;
}
//After connected, inner loop to read and write multiple packages
while(1) {
FD_ZERO(&set);
FD_SET(clientSockFd, &set);
timeout.tv_sec = 15;
timeout.tv_usec = 0;
rv = select(clientSockFd+1, &set, NULL, NULL, &timeout);
if(rv == -1) {
perror("select");
continue;
}
else if(rv == 0) {
printf("TCP timeout, closing client connection.\n");
shutdown(clientSockFd, 2);
break;
}
if (!readCommand(clientSockFd)) break;
}
close(clientSockFd);
}
close(serverSockFd);
return 0;
}
int readCommand(int sock) {
int nBytes;
int len;
char inBuf[BUF_SIZE];
char outBuf[BUF_SIZE];
nBytes = read(sock, inBuf, BUF_SIZE);
if(nBytes < 0) perror("ERROR reading from TCP socket");
else if(nBytes == 0) {
printf("Client closed TCP socket\n");
shutdown(sock, 2);
return nBytes;
}
else {
// Acknowledge command
len = sprintf(outBuf, "Command received: %s", inBuf);
if (write(sock, outBuf, len+1) < 0) {
perror("ERROR writing to TCP socket");
}
// Send response data
if (!strncmp("show version", inBuf, 12)) strcpy(outBuf, "Beta");
else strcpy(outBuf, "Invalid command");
if (write(sock, outBuf, strnlen(outBuf, BUF_SIZE-1)+1) < 0) {
perror("ERROR writing to TCP socket");
}
}
return nBytes;
}
I just realized both the acknowledgement and the data were consumed in the first read() when running the client on localhost.
So I need to parse the result of the first read before attempting a second.
I want to create a simple multithreaded chat application in C using api. For the beginning, i wrote a simple server communicating with client but there is a problem in the order messages sent.
example output:
in server
*new_sock socket number: 4
Server:hello client
Client:hello server
Server:how are you?
Client:
Server:
in client
Server:hello client
Client:hello server
Server:how are you?
Client:
//server code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <pthread.h>
void* connection_handler(void* socket_descriptor)
{
int socket = *(int *)socket_descriptor;
int n;
char server_buffer[256];
memset(server_buffer, 0, sizeof(server_buffer));
printf("Server:");
gets(server_buffer);
send(socket, server_buffer, strlen(server_buffer), 0);
memset(server_buffer, 0, sizeof(server_buffer));
while ((n = recv(socket, server_buffer, 255, 0)) > 0)
{
server_buffer[n] = '\0';
printf("Client:%s\n", server_buffer);
memset(server_buffer, 0, sizeof(server_buffer));
printf("Server:");
gets(server_buffer);
send(socket, server_buffer, strlen(server_buffer), 0);
memset(server_buffer, 0, sizeof(server_buffer));
n = 0;
}
close(socket);
free(socket_descriptor);
return 0;
}
int main(int argc, char *argv[])
{
int server_sock, client_sock, portno, client_len, n;
int *new_sock;
struct sockaddr_in server_addr, client_addr;
if(argc < 2)
{
printf("ERROR: no port provided.\n");
exit(1);
}
server_sock = socket(AF_INET, SOCK_STREAM, 0);
if(server_sock < 0)
{
printf("ERROR: opening socket.");
exit(1);
}
portno = atoi(argv[1]);
memset((char *)&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(portno);
server_addr.sin_addr.s_addr = INADDR_ANY;
if( bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0 )
{
printf("ERROR: binding socket.");
exit(1);
}
listen(server_sock, 5);
pthread_t handler_thread;
while( client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_len) )
{
new_sock = malloc(sizeof(int));
*new_sock = client_sock;
printf("*new_sock socket number: %d\n", *new_sock);
if( pthread_create(&handler_thread, (void *)NULL, connection_handler, (void *)new_sock) < 0)
{
printf("ERROR: creating thread\n");
exit(1);
}
}
pthread_join(handler_thread, NULL);
printf("server shut down.\n");
return 0;
}
//client code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int main(int argc, char* argv[])
{
int sock_descriptor, portno, n;
struct sockaddr_in server_addr;
char buffer[256];
if (argc != 2)
{
printf("usage: %s port\n", argv[0]);
exit(1);
}
portno = atoi(argv[1]);
sock_descriptor = socket(AF_INET, SOCK_STREAM, 0);
if (sock_descriptor < 0)
{
printf("ERROR: creating socket!\n");
exit(1);
}
memset((char *)&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(portno);
if (connect(sock_descriptor, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
printf("ERROR: connecting server!\n");
exit(1);
}
memset(buffer, 0, sizeof(buffer));
while((n = recv(sock_descriptor, buffer, 255, 0)) > 0)
{
buffer[n] = '\0';
printf("Server:%s\n", buffer);
memset(buffer, 0, sizeof(buffer));
printf("Client:");
gets(buffer);
send(sock_descriptor, buffer, sizeof(buffer), 0);
memset(buffer, 0, sizeof(buffer));
}
if (n <= 0)
{
printf("ERROR: reading from socket");
exit(1);
}
return 0;
}
Join the threads right after it has been created , accept is a blocking call (I assume you have not modified the default behavior) . Threads are complex to analyze however , the call to join wont even come since blocking accept call in while loop.
while(1)
{
//do something here
...
if( pthread_create(&handler_thread, (void *)NULL, connection_handler, (void *)new_sock) < 0)
{
printf("ERROR: creating thread\n");
exit(1);
}
pthread_join(handler_thread, NULL); //Use it right after creating thread
}
I'm making a client-server program in C using threads.
I've got this problem: on the server, on thread #1 (number_one), function "read" works fine. But when I create another thread #2 (number_two), on this one something goes wrong. Parameters are passed in the right way (I think).
-->thread number_one
...
char message[256];
int new_connection=accept(master_sock,NULL,NULL);
pthread_t temp
if(pthread_create(&temp , NULL , number_two , (void*) &new_connection))
{
perror("pthread_create failed");
exit(-2);
}
else
{
puts("number_two created");
if(read(new_connection, message, 256) > 0)
printf("Message from client is %s", message);
}
if(pthread_detach(temp))
{
perror("detach failed");
exit(-3);
}
...
---> thread number_two
void *number_two(void *sock_desc)
{
int sock = *(int*)sock_desc;
int read_size;
char client_message[2000];
read_size=read(sock, client_message, 256);
client_message[read_size]='\0';
return 0;
}
In "number_one", read waits an input from the client, and then it sets correctly the buffer "message".
In "number_two", read does not wait the client and does not set the buffer "client_message".
Thank you.
Please try my code? it works, I think it is the same with your code.
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netdb.h>
#define INVALID_SOCKET_FD (-1)
int create_tcp_server_socket(unsigned short port, bool bind_local, int backlog,
char *caller_name)
{
int socket_fd = INVALID_SOCKET_FD;
struct sockaddr_storage server_addr;
unsigned int yes = 1;
// just try ipv4
if (socket_fd < 0 && (socket_fd = socket(PF_INET, SOCK_STREAM, 0)) >= 0) {
struct sockaddr_in *s4 = (struct sockaddr_in *)&server_addr;
setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
memset(&server_addr, 0, sizeof(server_addr));
s4->sin_family = AF_INET;
s4->sin_port = htons(port);
if (bind_local)
s4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
else
s4->sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(socket_fd, (struct sockaddr *)&server_addr,
sizeof(server_addr)) < 0) {
close(socket_fd);
printf("Server: Failed to bind ipv4 server socket.\n");
return INVALID_SOCKET_FD;
}
}
else if (socket_fd < 0) {
printf("Server: Failed to create server socket.\n");
return INVALID_SOCKET_FD;
}
if (listen(socket_fd, backlog) < 0) {
close(socket_fd);
printf("Server: Failed to set listen.\n");
return INVALID_SOCKET_FD;
}
return socket_fd;
}
pthread_t temp;
void *number_two(void *sock)
{
char buf[1024];
int fd = *(int *)sock;
int nread = read(fd, buf, 1024);
write(STDOUT_FILENO, buf, nread);
return NULL;
}
int main()
{
pid_t pid;
if ((pid = fork()) < 0) {
}
else if (pid > 0) { // parent, server
char buf[1024];
int fd = create_tcp_server_socket(8787, false, 10, "zz");
int new_fd = accept(fd, NULL, 0);
pthread_create(&temp, NULL, number_two, (void *)&new_fd);
}
else { // child, client
uint32_t ip;
struct hostent *hp = gethostbyname("localhost");
memcpy(&ip, hp->h_addr_list[0], hp->h_length);
struct sockaddr_in server_addr;
memset((char *)&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = ip;
server_addr.sin_port = htons(8787);
int fd = socket(AF_INET, SOCK_STREAM, 0);
connect(fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
write(fd, "abcd", 4);
}
pause();
return 0;
}
When I type in to the terminal:
echo "GET /" | ./<executable name> www.google.com <port number, usually 80>
the terminal just sits there like it's waiting for input or it's stuck in an infinite loop. What is happening is that connection is taking too long I think.
/*Creating socket*/
int sock = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
printf("error creating socket\n");
exit(1);
}
printf("1\n");
/*Establish connection to the echo server*/
int r = connect(sock, addrList->ai_addr, addrList->ai_addrlen);
printf("1.5\n");
if (r < 0) {
perror("Connection failed\n");
exit(1);
}
printf("2\n");
Here, the 1 prints out, but the 1.5 right after the connect doesn't print out and the terminal just sits.
This problem didn't happen before and I used to get the page's source code back instantly. But now this problem is occurring.
It started occurring after I typed in to the terminal: netstat -an -A inet | grep :2525
so this may have had an effect.
Here is the entire code:
#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 <arpa/inet.h>
#include <netdb.h>
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("Invalid arguments\n");
exit(1);
}
char *serverIP = argv[1]; /*Server hostname*/
char *portNumber = argv[2]; /*Port Number*/
void *numericAddress;
char addrBuffer[INET6_ADDRSTRLEN];
in_port_t port;
char buffer_stdin[65535];
char buffer_stdout[65535];
int bytes_read = 0;
int bytes_written = 0;
/*getting integral number of string representation of port number*/
in_port_t servPort = atoi(argv[2]);
/*------------------get binary number of hostname-----------------*/
struct addrinfo addrCriteria;
memset(&addrCriteria, 0, sizeof(addrCriteria));
addrCriteria.ai_family = AF_INET;
addrCriteria.ai_socktype = SOCK_STREAM;
addrCriteria.ai_protocol = IPPROTO_TCP;
struct addrinfo *addrList;
int rtnVal = getaddrinfo(serverIP, portNumber, &addrCriteria, &addrList);
if (rtnVal != 0) {
printf("getaddrinfo() failed\n");
exit(1);
}
numericAddress = &((struct sockaddr_in *) (addrList->ai_addr))->sin_addr;
/*Converting port to binary*/
((struct sockaddr_in *)(addrList->ai_addr))->sin_port = htonl(servPort);
/*----------------------------------------------------------------*/
inet_ntop(addrList->ai_addr->sa_family, numericAddress, addrBuffer, sizeof(addrBuffer));
printf("IP ADDRESS: %s\n", addrBuffer);
/*Creating socket*/
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
printf("error creating socket\n");
exit(1);
}
/*printf("1\n");*/
/*Establish connection to the echo server*/
int r = connect(sock, addrList->ai_addr, addrList->ai_addrlen);
printf("%d\n", r);
if (r < 0) {
perror("Connection failed\n");
exit(1);
}
printf("2\n");
/*Reading from stdin and writing to socket until stdin ends
bytes_read = read(0, buffer_stdin, sizeof(buffer_stdin));
write(sock, buffer_stdin, bytes_read);*/
while ((bytes_read = read(0, buffer_stdin, sizeof(buffer_stdin)-1)) > 0) {
write(sock, buffer_stdin, bytes_read);
}
/*Shutting down write end of socket*/
int r_shutdown = shutdown(sock, SHUT_WR);
if (r_shutdown < 0) {
printf("Shutting down write end of socket failed\n");
exit(1);
}
/*Reading from socket and writing to stdout until socket ends*/
while ((bytes_read = read(sock, buffer_stdout, sizeof(buffer_stdout)-1)) > 0) {
write(1, buffer_stdout, bytes_read);
}
close(sock);
exit(0);
}
The correct way to do it is :
struct sockaddr_in address;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd!=-1)
{
perror("socket :");
printf("sockfd = %d\n", sockfd);
}
else
{
perror("socket");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = htons(9734);
len = sizeof(struct sockaddr_in);
result = connect(sockfd, (struct sockaddr *)&address, len);
Nvm I figured it out.
Apparently I had to take into account big endian vs little endian, and so in this line:
((struct sockaddr_in *)(addrList->ai_addr))->sin_port = htonl(servPort);
the htonl should've been htons, so:
((struct sockaddr_in *)(addrList->ai_addr))->sin_port = htons(servPort);