Socket addresing mechanism stuck - c

Basically i'm trying to do a server-client program that communicates with sockets.
I find it strange that the server, once started it doesn't even print the first line. Why is this?
There must be something that's sliping from me and I really need to know what.
Server.c
int rvsock;
void stop(int sig){
close(rvsock);
}
void* worker(void* p){
struct mymsg m;
int err;
int sock = (int)p;
err = recv(sock,&m,sizeof(m),0);
if(err < 0){
printf("Failed to receive");
exit(1);
}
m.a = ntohl(m.a);
m.b = ntohl(m.b);
m.c = ntohl(m.c);
m.ip = ntohl(m.ip);
printf("Received numbers: %d %d %d from IP:%d", m.a,m.b,m.c,m.ip);
if(m.a < m.b && m.b <= m.c)
m.a = m.c;
else if(m.a < m.b && m.b >= m.c)
m.a = m.b;
else if(m.a > m.b && m.b <= m.c)
m.a = m.a;
m.a = htonl(m.a);
m.b = htonl(m.b);
m.c = htonl(m.c);
err = send(sock, &m,sizeof(m),0);
if(err < 0){
printf("Failed to send!");
close(sock);
return NULL;
}
close(sock);
return NULL;
}
int main(int argc, char** argv) {
printf("DAFUQ"); //It doesn't even print this. Why?
int port;
int sock;
int err;
unsigned int len;
struct sockaddr_in saddr;
struct sockaddr_in caddr;
pthread_t w[100];
int wn = 0;
int i;
sscanf(argv[1], "%d", &port);
signal(SIGINT, stop);
rvsock = socket(AF_INET, SOCK_STREAM, 0);
if(rvsock < 0) {
perror("Failed to create socket");
exit(1);
}
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
saddr.sin_port = htons(port);
err = bind(rvsock, (struct sockaddr*)&saddr,
sizeof(struct sockaddr_in));
if(err < 0) {
perror("Failed to bind");
exit(1);
}
err = listen(rvsock, 5);
if(err < 0) {
perror("Failed to listen");
close(rvsock);
exit(1);
}
while(1) {
len = sizeof(struct sockaddr_in);
sock = accept(rvsock, (struct sockaddr*)&caddr, &len);
if(sock < 0) {
perror("Failed to accept");
break;
}
pthread_create(&w[wn], 0, worker, (int*)sock);
wn++;
}
for(i=0; i<wn; i++) {
pthread_join(w[i], 0);
}
return 0;
}
client.c
int main(int argc, char** argv){
int sock;
int err;
int port;
struct sockaddr_in saddr;
struct mymsg m;
sscanf(argv[1], "%d", &port);
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0){
printf("failed to create");
exit(1);
}
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
saddr.sin_port = htons(port);
err = connect(sock, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));
if(err < 0){
perror("Failed to connect!");
exit(1);
}
printf("give a:");scanf("%d",&m.a);
printf("give b:");scanf("%d",&m.b);
printf("give c:");scanf("%d",&m.c);
m.a = htonl(m.a);
m.b = htonl(m.b);
m.c = htonl(m.c);
send(sock,&m,sizeof(m),0);
return 0;
}
message.h
struct mymsg{
int a;
int b;
int c;
int ip;
};

In your server you have this line. printf prints to the stdout FILE which is opened for you when you start your program.
printf("DAFUQ"); //It doesn't even print this. Why?
man stdout provides the following information about stdout:
The stream stdout is line-buffered
when it points to a terminal. Partial lines will not appear until
fflush(3) or exit(3) is called, or a newline is printed.
You don't print a newline, you don't flush stdout and your program doesn't exit, therefore none of the conditions required to print your output to the terminal are met.
Therefore in order to print the line you have 3 options:
1
printf("DAFUQ"); //It doesn't even print this. Why?
fflush(stdout);
2
printf("DAFUQ\n"); /*notice added '\n'*/
3
call exit() after you print ( not very helpful probably).

Related

How to use select and accept to communicate with clients properly?

I have read some example and manual about select and accept but I still can't figure out where I did wrong.
I tried to let server communicate with multiple clients. But when I execute server first, then execute client, server will immediately cause segmentation fault( when i == sockfd in server.c). And I tried to print some strings to check which statement cause wrong, it even no print anything after if (i == sockfd). So I really have no idea how to move on, are there any suggestion?
Server.c
char inputBuffer[140] = {};
char message[] = {"Hi,this is server.\n"};
int sockfd = 0,forClientSockfd = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
printf("Fail to create a socket.");
}
//socket creation
struct sockaddr_in serverInfo,clientInfo;
socklen_t addrlen = sizeof(clientInfo);
serverInfo.sin_family = PF_INET;
serverInfo.sin_addr.s_addr = INADDR_ANY;
serverInfo.sin_port = htons(PORT);
bind(sockfd,(struct sockaddr *)&serverInfo,sizeof(serverInfo));
listen(sockfd,5);
fd_set active_fd_set, read_fd_set;
int i;
struct sockaddr_in clientname;
size_t size;
/* Initialize the set of active sockets. */
FD_ZERO (&active_fd_set);
FD_SET (sockfd, &active_fd_set);
int fd_max = sockfd;
while (1)
{
/* Block until input arrives on one or more active sockets. */
//FD_ZERO (&active_fd_set);
//FD_SET (sockfd, &active_fd_set);
read_fd_set = active_fd_set;
if (select (fd_max+1, &read_fd_set, NULL, NULL, NULL) < 0)
{
printf("select fail\n");
}
/* Service all the sockets with input pending. */
for (i = 0; i <= fd_max; ++i)
{
//printf("%d\n",i);
if (FD_ISSET (i, &read_fd_set))
{
//printf("inner :%d %d\n",i,sockfd);
if (i == sockfd)
{
/* Connection request on original socket. */
//printf("A");
int new;
size = sizeof (clientname);
new = accept (sockfd,(struct sockaddr *) &clientname,&size);
if (new < 0)
{
printf("accept fail\n");
}
else
{
printf (
"Server: connect from host %s, port %hd.\n",
inet_ntoa (clientname.sin_addr),
ntohs (clientname.sin_port));
FD_SET (new, &active_fd_set);
if(new > fd_max)
{
fd_max = new;
}
}
}
else
{
/* Data arriving on an already-connected socket. */
if (read_from_client (i) < 0)
{
close (i);
FD_CLR (i, &active_fd_set);
}
}
}
}
}
return 0;
}
int read_from_client (int filedes)
{
char buffer[140];
int nbytes;
nbytes = recv (filedes, buffer, sizeof(buffer),0);
if (nbytes < 0)
{
/* Read error. */
perror ("read");
exit (EXIT_FAILURE);
}
else if (nbytes == 0)
/* End-of-file. */
return -1;
else
{
/* Data read. */
printf ("Server: got message: `%s'\n", buffer);
return 0;
}
}
client.c
int sockfd = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
printf("Fail to create a socket.");
}
//socket connnection
struct sockaddr_in info;
bzero(&info,sizeof(info));
info.sin_family = PF_INET;
//localhost test
info.sin_addr.s_addr = inet_addr(LOCALHOST);
info.sin_port = htons(PORT);
int err;
char *p;
//Send a message to server
err = connect(sockfd,(struct sockaddr *)&info,sizeof(info));
if(err==-1)
printf("Connection error");
while(1)
{
char message[140];
char receiveMessage[140] = {};
fgets(message,140,stdin);
//scanf("%*[^\n]",message);
//printf("%s",message);
/*if(p=strchr(message,'\n')){
*p = 0;
}else{
scanf("%*[^\n]");
scanf("%c");
}
fgets(message,140,stdin);*/
//scanf("%s",message);
send(sockfd,message,sizeof(message),0);
//printf("RCV");
//recv(sockfd,receiveMessage,sizeof(receiveMessage),0);
//printf("%s\n",receiveMessage);
}
thanks !!

Multiple Client single server using select

he server is accepting the clients, but no message is received. Here is my code for server:
Server:
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<stdbool.h>
#include<sys/select.h>
#include<errno.h>
//Socket Creation
int socketFile(){
int Socket = socket(AF_INET, SOCK_STREAM, 0);
if(Socket == -1){
perror("Socket Error\n");
exit(1);
}
else
printf("Successfullly Connected to Socket: %d\n",Socket);
return Socket;
}
int bindFile(int Socket, const struct sockaddr * receiver, int len){
int Bind = bind(Socket, receiver, len);
if(Bind == -1){
perror("Bind Error\n");
exit(1);
}
else
printf("Successfullly Connected with Bind number: %d\n", Bind);
}
int listenFile(int Socket, int n){
int listen1 = listen(Socket, n);
if(listen1 == -1){
perror("listen Error\n");
exit(1);
}
else
printf("Successfully Connected with no Listen Error\n");
}
int acceptFile(int Socket, struct sockaddr * receiver, socklen_t addrlen){
int accept1 = accept(Socket, (struct sockaddr *)&receiver, &addrlen);
if(accept1 == -1){
perror("accept Error\n");
exit(1);
}
else
printf("Successfully Accepted with Data Socket number: %d\n", accept1);
}
void clearBuffer(char* b, int len) {
int i;
for (i = 0; i < len; i++)
b[i] = '\0';
sleep(0.1);
}
int main(int abcd, char *args[]) {
//Socket
int Socket = socketFile();
//Struct for Receiver
struct sockaddr_in receiver, sender;
receiver.sin_family = AF_INET;
receiver.sin_port = htons(atoi(args[1]));
receiver.sin_addr.s_addr = inet_addr("127.0.0.1");
int addrlength = sizeof(sender);
socklen_t senderLength;
//Bind
int Bind = bindFile(Socket, (const struct sockaddr *)&receiver, addrlength);
//Listen
int Listen = listenFile(Socket, 5);
char buffer[21];
clearBuffer(buffer, 20);
int message, set = 0, Select, client[30], max_client = 30, i, max_set = Socket;
fd_set readfds, fds;
struct timeval timeout;
for(i = 0; i < max_client; i++){
client[i] = 0;
}
//Clear & Add
FD_ZERO(&fds);
FD_SET(Socket, &fds);
bool stop = false;
while(!stop) {
readfds = fds;
Select = select(max_set +1, &readfds, NULL, NULL, NULL);
if (Select == -1) {
perror("Select");
break;
}
if(FD_ISSET(Socket, &readfds)) {
if(set < max_client) {
client[set] = acceptFile(Socket,(struct sockaddr *) &sender, senderLength);
FD_SET(client[set], &fds);
if(client[set] > max_set)
max_set = client[set];
set++;
}
}
for(i = 0; i < set; i++) {
if(FD_ISSET(client[i], &readfds)){
message = recv(client[i], buffer, 20, 0);
buffer[message] = '\0';
printf("%s\n", buffer);
}
}
}
close(Socket);
return 0;
}
The client part is okay but after connecting to the server and the sending the first message, the server is not able to receive the message.
I having a lot of trouble dealing with the error. So please rectify the error.
You should enable all warnings. Then you'd see the reason immediately: acceptFile does not return anything, therefore client[set] is set to garbage.

unix network programming select function always return 1( resoved)

learning the socket programming in c
use gdb tcpserv , select function always return 1 , i don`t kown why.
not good at english, so i paste the code here. anyone help?
file: sockheader.h
content :
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string.h>
#include <signal.h>
#include <sys/select.h>
#define SERV_PORT 11211
#define SA struct sockaddr
#define LISTENQ 5
#define MAXLINE 1024
typedef void Sigfun(int);
int Socket(int family, int type, int protocol);
int Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
int Listen(int sockfd, int backlog);
int Accept(int sockfd, struct sockaddr *chiaddr, socklen_t *addrlen);
int Close(int sockfd);
int Connect(int sockfd, const struct sockaddr *sa, socklen_t salen);
void Writen(int sockfd, char *writeline, int len);
int str_echo(int sockfd);
int str_echo2sum(int sockfd);
int str_cli(int sockfd);
void sig_chld(int signo);
file: sockheader.c
content:
#include "sockheader.h"
int Socket(int family, int type, int protocol)
{
int fd;
if( (fd = socket(family, type, protocol)) < 0 )
{
perror("socket error!\n");
exit(-1);
}
return fd;
}
int Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen)
{
int bindfd;
if( (bindfd = bind(sockfd, myaddr, addrlen)) < 0 )
{
perror("bind error");
exit(-1);
}
return bindfd;
}
int Listen(int sockfd, int backlog)
{
int res ;
if( (res = listen(sockfd, backlog) ) < 0 )
{
perror("Listen error");
exit(-1);
}
return res;
}
int Accept(int sockfd, struct sockaddr *chiaddr, socklen_t *addrlen)
{
int res ;
if( (res = accept(sockfd, chiaddr, addrlen)) < 0 )
{
perror("accept error");
exit(-1);
}
return res;
}
int Close(int sockfd)
{
close(sockfd);
}
int Connect(int sockfd, const struct sockaddr *sa, socklen_t salen)
{
int res ;
if ( (res = connect(sockfd, sa, salen)) < 0)
perror("connect error");
return res;
}
void Writen(int sockfd, char *writeline, int len)
{
write(sockfd, writeline, len);
}
int str_echo(int sockfd)
{
char readline[MAXLINE];
char sendline[MAXLINE];
int n;
again:
while( (n = read(sockfd, readline, MAXLINE)) > 0 )
{
fputs("read str:\n", stdout);
readline[n] = '\0';
strcpy(sendline, "recive str:");
strcat(sendline, readline);
Writen(sockfd, sendline, strlen(sendline) + 1);
if(fputs(readline, stdout) == EOF)
{
perror("fputs error");
}
}
fputs("out while\n", stdout);
if (n < 0 )
goto again;
}
int str_echo2sum(int sockfd)
{
long arg1, arg2;
char readline[MAXLINE];
int n;
again:
while( (n = read(sockfd, readline, MAXLINE)) > 0 )
{
if( sscanf(readline, "%ld%ld", &arg1, &arg2) == 2 )
{
snprintf(readline, sizeof(readline), "%ld\n", arg1 + arg2);
}
else
{
snprintf(readline, sizeof(readline), "input error\n");
}
n = strlen(readline);
Writen(sockfd, readline, strlen(readline) + 1);
if(fputs(readline, stdout) == EOF)
{
perror("fputs error");
}
}
fputs("out while\n", stdout);
if (n < 0 )
goto again;
}
int str_cli(int sockfd)
{
char charline[MAXLINE], recvline[MAXLINE];
while(fgets(charline, MAXLINE, stdin) != NULL)
{
fputs("write string\n", stdout);
Writen(sockfd, charline, strlen(charline) + 1);
if(read(sockfd, recvline, MAXLINE) == 0)
{
perror("str_cli:server terminated prematurely");
}
if(fputs(recvline, stdout) == EOF)
{
perror("fputs error");
}
}
fputs("cli:out while\n", stdout);
}
int str_cli2(int sockfd)
{
int maxfd1, stdineof;
fd_set rset;
char buf[MAXLINE];
int n;
stdineof = 0;
FD_ZERO(&rset);
for(;;)
{
if(stdineof == 0)
{
FD_SET(fileno(stdin), &rset);
}
FD_SET(sockfd, &rset);
maxfd1 = fileno(stdin) > sockfd ? fileno(stdin) + 1 : sockfd + 1 ;
select(maxfd1, &rset, NULL, NULL, NULL);
if(FD_ISSET(sockfd, &rset))
{
if( ( n = read(sockfd, buf, MAXLINE) ) == 0)
{
if(stdineof == 1)
{
return ;
}
else
{
perror("str_cli2:server terminated ");
exit(-1);
}
}
Writen(fileno(stdout), buf, n );
}
if( FD_ISSET(fileno(stdin), &rset) )
{
if( ( n = read(stdin, buf, MAXLINE) ) == 0)
{
stdineof = 1;
shutdown(sockfd, SHUT_WR);
FD_CLR(fileno(stdin), &rset);
continue;
}
Writen(sockfd, buf, n);
}
}
}
void sig_chld(int signo)
{
pid_t pid;
int stat;
while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
{
printf("child %d terminated\n", pid);
}
return;
}
file:tcpcli05.c
content:
#include "sockheader.h"
int main(int argc, char const *argv[])
{
int sockfd, i;
struct sockaddr_in cliaddr;
for(i = 0; i < 5; i++)
{
sockfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&cliaddr, sizeof(cliaddr));
cliaddr.sin_family = AF_INET;
cliaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, argv[1], &cliaddr.sin_addr.s_addr);
Connect(sockfd, (SA *)&cliaddr, sizeof(cliaddr));
}
str_cli2(sockfd);
return 0;
}
file:tcpserv05.c
content:
#include "sockheader.h"
int main(int argc, char const *argv[])
{
int i, maxi, maxfd, listenfd, sockfd, connfd;
int nready, client[FD_SETSIZE];
ssize_t n ;
fd_set rset, allset;
char buf[MAXLINE];
struct sockaddr_in servaddr, chiladdr;
socklen_t chlien;
pid_t pid;
sockfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
// inet_pton(AF_INET, INADDR_ANY, &servaddr.sin_addr);
Bind(sockfd, (SA *)&servaddr, sizeof(servaddr));
Listen(sockfd, LISTENQ);
// signal(SIGCHLD, sig_chld);
maxfd = sockfd;
maxi = -1;
for(i = 0; i < FD_SETSIZE; i++)
{
client[i] = -1;
}
FD_ZERO(&allset);
FD_SET(sockfd, &allset);
for(;;)
{
rset = allset;
printf("i walk here \n");
nready = select(maxfd + 1, &rset, NULL, NULL, NULL);
printf("nready:%d\n", nready);
if(FD_ISSET(sockfd, &rset))
{
chlien = sizeof(chiladdr);
if(( connfd = Accept(sockfd, (SA *)&chiladdr, &chlien )) < 0)
{
perror("accept error");
}
printf("new client: %d\n", inet_ntoa(chiladdr.sin_addr));
printf("new client port: %d\n", ntohs(chiladdr.sin_port));
for(i = 0; i < FD_SETSIZE; i++)
{
if(client[i] < 0)
{
client[i] = connfd;
break;
}
}
if(i == FD_SETSIZE)
{
perror("too many clients");
}
printf("connfd: %d\n", connfd);
FD_SET(connfd, &allset);
if(connfd > maxfd)
{
maxfd = connfd;
}
if(i > maxi)
{
maxi = i;
}
if(--nready <= 0 )
{
continue;
}
}
printf("i walk down here \n");
for( i = 0 ; i <= maxi; i++)
{
if( (listenfd = client[i]) < 0)
{
continue;
}
if(FD_ISSET(listenfd, &rset))
{
if( (n = read(listenfd, buf, MAXLINE)) == 0 )
{
Close(listenfd);
FD_CLR(listenfd, &allset);
client[i] = -1;
}
else
{
Writen(listenfd, buf, n);
}
if( --nready < 0 )
{
continue;
}
}
}
}
return 0;
}
then
gcc -o tcpserv05 -g sockheader.c tcpserv05.c
gcc -o tcpcli05 -g sockheader.c tcpcli05.c
./tcpserv05
./tcpcli05 127.0.0.1
in the cli, i input some thing like "hi, test". the serv do not return anything .
i gdb tcpserv05 then found the nready is always 1 . so --nready <= 0 is true, continue.
program did not go to below.
i need some help, thank you first.
#
I find the problem.
I wrote the wrong code :
read(stdin, buf, MAXLINE)
stdin is FILE * , fread、fwrite、fclose will use stdin.
ssize_t read(int fd, void *buf, size_t count);
so i use fileno(stdin) instead, program worked.
select returns 1, because that is the number of file descriptors that have events. If you had a timeout, it would return 0, if more file descriptors had events, it would return a higher number.
You might want to use poll(2) instead of the older select(2). Read about the C10K problem.
Since select may modify its fd_set bitmasks, you should set them inside the loop (often, fd_set is just an array, so assigning rset = allset; don't do what you want).
Don't forget to call fflush(3) at appropriate places (e.g. fflush(NULL) before any select or poll)
Consider also using strace(1) for debugging.
Always test every syscalls(2) for failure (using perror)
See comments for this related question.
Always compile with gcc -Wall -Wextra -g and improve your source code till you get no warnings at all. BTW, bzero(3) is explicitly deprecated (i.e. obsolete) and you should not use it.

Sockets behavior differently between BSD (Mac OS X and OpenBSD) and Linux (Ubuntu)

I wrote a man-in-the-middle/proxy server initially on my mac. Essentially the proxy creates a socket and waits for a connection, then connects to another application. This works flawlessly on in OS X and in OpenBSD; however, when porting the proxy to Ubuntu, it doesn't work as intended.
There is two instances of this proxy running, listening on two separate ports. When this is ran on Ubuntu, all the traffic goes through a single port. I also run into a problem when setting the socket to nonblocking (through fcntl) that sometimes it fails with "Invalid Argument"
I am using sys/socket.
Any pitfalls during this port that I am missing?
EDIT:
I believe there are two problems. One being the Invalid Argument, the other being that traffic is being pushed to different ports.
Service 1 binds to Proxy instance 1 which then binds back to the appropriate service on the black box, which kicks off service 2. However, for some reason on Ubuntu it connects to the Instance 1 which is listening on the incorrect port.
EDIT Solution to Invalid Argument for fcntl:
Found out why i was getting the invalid argument, sadly i'm still having the other issue.
fcntl(fd, cmd, arg)
cmd - F_SETFL(long)
I was passing in a pointer to an int instead of the long primitive.
EDIT:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <netdb.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/ftp.h>
#include <arpa/inet.h>
#include <arpa/telnet.h>
void cleanup(int sig)
{
syslog(LOG_INFO, "Cleaning up...");
exit(0);
}
void sigreap(int sig)
{
int status;
pid_t p;
while ((p = waitpid(-1, &status, WNOHANG)) > 0) {
syslog(LOG_INFO, "sigreap: pid=%d, status=%d\n", (int) p, status);
}
/* doh! */
signal(SIGCHLD, sigreap);
}
void set_nonblock(int fd)
{
long fl;
int x;
fl = fcntl(fd, F_GETFL);
if (fl < 0) {
syslog(LOG_ERR, "fcntl F_GETFL: FD %d: %s", fd, strerror(errno));
exit(1);
}
fl |= O_NONBLOCK;
x = fcntl(fd, F_SETFL, fl);
if (x < 0) {
syslog(LOG_ERR, "fcntl F_SETFL: FD %d: %s", fd, strerror(errno));
exit(1);
}
}
int create_server_sock(char *addr, int port)
{
int addrlen, s, on = 1, x;
static struct sockaddr_in client_addr;
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0)
perror("socket"), exit(1);
addrlen = sizeof(client_addr);
memset(&client_addr, '\0', addrlen);
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = INADDR_ANY; //inet_addr(addr);
client_addr.sin_port = htons(port);
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, 4);
x = bind(s, (struct sockaddr *) &client_addr, addrlen);
if (x < 0)
perror("bind"), exit(1);
x = listen(s, 5);
if (x < 0)
perror("listen"), exit(1);
return s;
}
int open_remote_host(char *host, int port)
{
struct sockaddr_in rem_addr;
int len, s, x;
struct hostent *H;
int on = 1;
H = gethostbyname(host);
if (!H)
return (-2);
len = sizeof(rem_addr);
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0)
return s;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, 4);
len = sizeof(rem_addr);
memset(&rem_addr, '\0', len);
rem_addr.sin_family = AF_INET;
memcpy(&rem_addr.sin_addr, H->h_addr, H->h_length);
rem_addr.sin_port = htons(port);
x = connect(s, (struct sockaddr *) &rem_addr, len);
if (x < 0) {
close(s);
return x;
}
set_nonblock(s);
return s;
}
int get_hinfo_from_sockaddr(struct sockaddr_in addr, int len, char *fqdn)
{
struct hostent *hostinfo;
hostinfo = gethostbyaddr((char *) &addr.sin_addr.s_addr, len, AF_INET);
if (!hostinfo) {
sprintf(fqdn, "%s", inet_ntoa(addr.sin_addr));
return 0;
}
if (hostinfo && fqdn)
sprintf(fqdn, "%s [%s]", hostinfo->h_name, inet_ntoa(addr.sin_addr));
return 0;
}
int wait_for_connection(int s)
{
int newsock;
socklen_t len;
static struct sockaddr_in peer;
len = sizeof(struct sockaddr);
newsock = accept(s, (struct sockaddr *) &peer, &len);
/* dump_sockaddr (peer, len); */
if (newsock < 0) {
if (errno != EINTR)
perror("accept");
}
get_hinfo_from_sockaddr(peer, len, client_hostname);
set_nonblock(newsock);
return (newsock);
}
static int print_bytes(char * buf, ssize_t length)
{
int i = 0, ascii_off = 0, hex_off = 0;
char * hex_bytes = (char *) calloc(32*2,1);
char * ascii_bytes = (char *) calloc(32*2,1);
for( i = 0; i < length; i++)
{
hex_off += sprintf(hex_bytes+hex_off,"%02X ",(unsigned char)buf[i]);
if(buf[i] >= '!' && buf[i] <= '~')
ascii_off += sprintf(ascii_bytes+ascii_off,"%c ",buf[i]);
else
ascii_off += sprintf(ascii_bytes+ascii_off,". ");
if( ((i+1) % 16 == 0) || i == length-1 )
{
fprintf(stderr,"%-48s\t%s\n",hex_bytes,ascii_bytes);
free(hex_bytes);
free(ascii_bytes);
hex_bytes = (char *) calloc(32*2,1);
ascii_bytes = (char *) calloc(32*2,1);
ascii_off = 0;
hex_off = 0;
if(i != length-1)
fprintf(stderr,"\t");
}
}
free(hex_bytes);
free(ascii_bytes);
return 0;
}
int mywrite(int fd, char *buf, int *len)
{
int x = write(fd, buf, *len);
print_bytes(buf,*len);
if (x < 0)
return x;
if (x == 0)
return x;
if (x != *len)
memmove(buf, buf+x, (*len)-x);
*len -= x;
return x;
}
void service_client(int fd1, int fd2, int injfd)
{
int maxfd;
cfd = fd1;
sfd = fd2;
char *sbuf;
char *cbuf;
int x, n;
int cbo = 0;
int sbo = 0;
int ibo = 0;
fd_set R;
int max_clients = 30;
int i = 0,s = 0, addrlen;
struct sockaddr_in address;
sbuf = malloc(BUF_SIZE);
cbuf = malloc(BUF_SIZE);
cntrlbuf = calloc(1,BUF_SIZE);
char * injbuf = malloc(BUF_SIZE);
maxfd = cfd > sfd ? cfd : sfd;
maxfd = injfd > maxfd ? injfd : maxfd;
maxfd++;
maxfd++;
struct inj_con * ptr;
while (1) {
struct timeval to;
if (cbo) {
process_packet(cbuf,&cbo,sfd);
}
if (sbo) {
process_packet(sbuf,&sbo,cfd);
}
if (ibo) {
process_packet(injbuf,&ibo,cfd);
}
if (cntrlo) {
fprintf(stderr,"\033[33;1mControl->(%d), len = 0x%x (%d):\033[0m\n\t",cfd,cntrlo,cntrlo);
if (mywrite(cfd, cntrlbuf, &cntrlo) < 0 && errno != EWOULDBLOCK) {
syslog(LOG_ERR, "write %d: %s", cfd, strerror(errno));
exit(1);
}
}
FD_ZERO(&R);
if (cbo < BUF_SIZE)
FD_SET(cfd, &R);
if (sbo < BUF_SIZE)
FD_SET(sfd, &R);
if (ibo < BUF_SIZE)
FD_SET(injfd, &R);
to.tv_sec = 0;
to.tv_usec = 1000;
x = select(max_clients+3, &R, 0, 0, &to);
if (x > 0 || cntrl_q->item_count > 0) {
if (FD_ISSET(injfd, &R)) {
int new_socket;
if((new_socket = accept(injfd, (struct sockaddr *) &address, (socklen_t *) &addrlen)) < 0)
{
perror("accept");
exit(1);
}
// Truncated
//
}
char * temp_pkt;
if (FD_ISSET(cfd, &R)) {
temp_pkt = (char *) calloc(BUF_SIZE,1);
n = read(cfd, temp_pkt, BUF_SIZE);
syslog(LOG_INFO, "read %d bytes from CLIENT (%d)", n, cfd);
if (n > 0) {
push_msg(s_q,temp_pkt,n);
} else {
free(temp_pkt);
close(cfd);
close(sfd);
close_injection_sockets();
close(injfd);
_exit(0);
}
}
if (FD_ISSET(sfd, &R)) {
temp_pkt = (char *) calloc(BUF_SIZE,1);
n = read(sfd, temp_pkt, BUF_SIZE);
syslog(LOG_INFO, "read %d bytes from SERVER (%d)\n", n, sfd);
if (n > 0) {
push_msg(c_q,temp_pkt,n);
} else {
free(temp_pkt);
close(sfd);
close(cfd);
close_injection_sockets();
close(injfd);
_exit(0);
}
}
if(cntrlo == 0 && cntrl_q->front != NULL)
{
struct msg * tmp = next_msg(cntrl_q);
if(tmp != NULL)
{
memcpy(cntrlbuf,tmp->msg,tmp->len);
cntrlo += tmp->len;
free(tmp->msg);
free(tmp);
}
}
if(sbo == 0 && c_q->front != NULL)
{
struct msg * tmp = next_msg(c_q);
if(tmp != NULL)
{
memcpy(sbuf,tmp->msg,tmp->len);
sbo += tmp->len;
free(tmp->msg);
free(tmp);
}
}
if(cbo == 0 && s_q->front != NULL)
{
struct msg * tmp = next_msg(s_q);
if(tmp != NULL)
{
memcpy(cbuf,tmp->msg,tmp->len);
cbo += tmp->len;
free(tmp->msg);
free(tmp);
}
}
if(ibo == 0 && inj_q->front != NULL)
{
struct msg * tmp = next_msg(inj_q);
if(tmp != NULL)
{
memcpy(injbuf,tmp->msg,tmp->len);
ibo += tmp->len;
free(tmp->msg);
free(tmp);
}
}
} else if (x < 0 && errno != EINTR) {
close(sfd);
close(cfd);
_exit(0);
}
}
}
static int create_injection_sock(int injectionport)
{
struct sockaddr_in serv_addr;
int portno = injectionport;
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd <0)
{
perror("ERROR: opening socket");
exit(1);
}
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(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
perror("ERROR: on bind");
exit(1);
}
if (listen(sockfd,5) < 0 )
{
perror("listen injection");
exit(1);
}
return sockfd;
}
int main(int argc, char *argv[])
{
if (!(5 == argc || 6 == argc)) {
fprintf(stderr, "usage: %s laddr lport rhost rport [injectionport]\n", argv[0]);
exit(1);
}
char *localaddr = strdup(argv[1]);
int localport = atoi(argv[2]);
char *remoteaddr = strdup(argv[3]);
int remoteport = atoi(argv[4]);
int injectionport;
if(argc == 6)
injectionport = atoi(argv[5]);
int client, server;
int master_sock;
int injection_sock = -1;
cntrl_q = (struct item_queue *) calloc(1,sizeof(struct item_queue));
inj_q = (struct item_queue *) calloc(1,sizeof(struct item_queue));
s_q = (struct item_queue *) calloc(1,sizeof(struct item_queue));
c_q = (struct item_queue *) calloc(1,sizeof(struct item_queue));
identities = (struct item_queue *) calloc(1,sizeof(struct item_queue));
assert(localaddr);
assert(localport > 0);
assert(remoteaddr);
assert(remoteport > 0);
if(argc == 6)
assert(injectionport > 0);
openlog(argv[0], LOG_PID, LOG_LOCAL4);
signal(SIGINT, cleanup);
signal(SIGCHLD, sigreap);
if(argc == 6)
injection_sock = create_injection_sock(injectionport);
master_sock = create_server_sock(localaddr, localport);
for (;;) {
if ((client = wait_for_connection(master_sock)) < 0)
continue;
if ((server = open_remote_host(remoteaddr, remoteport)) < 0)
continue;
if (!fork()) {
service_client(client, server, injection_sock);
}
close(client);
close(server);
}
}
Just a guess, but I think your problem is the way you're handling the injection socket. I don't know what you deleted in the // TRUNCATED code block, but basically what you're doing is this:
// Parent process -- bind & listen on the injection socket
injfd = socket(...);
bind(injfd, ...);
listen(injfd, ...);
...
while (1)
{
client = wait_for_connection();
...
if (!fork())
{
// Each child process
...
if (stuff && FD_ISSET(injfd, &R)) {
new_socket = accept(injfd);
...
}
...
}
...
}
In other words, all of your child processes are listening on the same injection socket and trying to accept connections. I'm not sure if this even well-defined behavior, but even in the best case, when a new connection arrives on the injection port, the process that is going to accept the connection could be random and uncontrollable. It could be any of the child processes or even the parent process.
In order to control that behavior, you need to decide who should be listening for connections on the injection socket. If only the parent should be listening, then only the parent should call accept() on it or pass it as an argument to select(). Likewise, if only a particular child should be listening, then only that child should call accept() or pass it to select(). All other processes that are ignoring that socket should close() it at their earliest convenience (e.g. immediately after fork() returns) to avoid leaking file descriptors.
Turns out that SO_REUSEADDR socket option was the issue. I removed me setting that socket option and everything worked out.
This Lead me to the solution.

Can't close non-blocking UDP socket in C Fedora16

I built very basic UDP chat using C language and Fedora 16 OS.
When my server connect, he got 5 ports and listen to them.
My problem is: when I'm trying to connect to the server with new client but gives him port that my server don't know, I want him to exit Immediately.
I don't know how to check the "MSG_DONTWAIT" flag.
Here is my code:
Server side:
#define MAX_MESSAGE_SIZE 1024
#define SERVER_CONNECTIONS 5
// Implementation of server that manages a chat.
#include "server.h"
int main(int argc,char* argv[])
{
if(argc != 2) //check if user insert more then one argument to the program
{
printf("Usage server <port>\n‬‬");
fflush(stdout);
exit (-1);
}
/*!
========Server creation flow:========
1) create the socket
2) bind the socket to a port
3) recvfrom (read from socket)
4) sendto (close the socket)
5) close the socket
*/
//!------------------------------------- 1) create the socket-------------------------------------
//!------------------------------- 2) bind the socket to a port-----------------------------------
int fd[SERVER_CONNECTIONS]; //socket descriptor
int port[SERVER_CONNECTIONS]; //socket fd port
int i=0;
for(i=0; i<SERVER_CONNECTIONS; i++)
{
port[i] = atoi(argv[1])+i;
}
create_sockets(fd, port);
char buf[MAX_MESSAGE_SIZE]; //used by read() & write()
int maxfd = find_maxfd(fd);
struct sockaddr_in cli; //used by read() & write()
int cli_len = sizeof(cli); //used by read() & write()
fd_set readfds;
fd_set writefds;
struct timeval timeout;
timeout.tv_sec = 1;
int nbytes=0;
while(1)
{
FD_ZERO(&readfds);
FD_ZERO(&writefds);
for(i=0; i<SERVER_CONNECTIONS; i++)
{
FD_SET(fd[i], &readfds);
FD_SET(fd[i], &writefds);
}
/* Now use FD_SET to initialize other fd’s that have already been returned by accept() */
if (select(maxfd+1, &readfds, 0, 0, 0) < 0)
{
perror("select");
exit(1);
}
for(i=0; i<SERVER_CONNECTIONS; i++)
{
//!------------------------------- recvfrom (read from socket)-----------------------------------
if(FD_ISSET(fd[i], &readfds))
{
fprintf(stderr, "ready to read from %d\n", fd[i]);
memset(&buf, 0, sizeof(buf)); //init buf
if((nbytes = recvfrom(fd[i], buf, sizeof(buf), 0 /* flags */, (struct sockaddr*) &cli, (socklen_t*)&cli_len)) < 0)
{
perror("recvfrom");
exit(1);
}
//!------------------------------- sendto (close the socket)-----------------------------------
FD_ZERO(&writefds);
FD_SET(fd[i], &writefds);
if (select(maxfd+1, 0, &writefds, 0, &timeout) < 0)
{
perror("select");
exit(1);
}
if(FD_ISSET(fd[i], &writefds))
{
fprintf(stderr, "ready to write to %d\n", fd[i]);
string_to_hex(buf);
if ((nbytes = sendto(fd[i], buf, strlen(buf), 0 /* flags */, (struct sockaddr*) &cli, sizeof(cli))) < 0)
{
perror("sendto");
exit(1);
}
}
}
}
}
return 0;
}
void create_sockets(int fd[], int port[])
{
int i=0;
for(i=0; i<SERVER_CONNECTIONS; i++)
{
//!------------------------------------- 1) create the socket-------------------------------------
if((fd[i] = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket");
exit(1);
}
//!------------------------------- 2) bind the socket to a port-----------------------------------
struct sockaddr_in srv; //used by bind()
srv.sin_family = AF_INET; //use the Internet address family
srv.sin_port = htons(port[i]); //socket ‘fd’ to port
srv.sin_addr.s_addr = htonl(INADDR_ANY); //a client may connect to any of my addresses
if(bind(fd[i], (struct sockaddr*) &srv, sizeof(srv)) < 0)
{
perror("bind");
exit(1);
}
}
}
int find_maxfd(int fd[])
{
int i=0;
int res=fd[0];
for(i=1; i<SERVER_CONNECTIONS; i++)
{
if(fd[i]>res)
{
res = fd[i];
}
}
return res;
}
void string_to_hex(char buf[])
{
int buf_size = strlen(buf);
char result[buf_size*3+1];
memset(&result, 0, sizeof(result));
char temp[4];
int i=0;
for (i=0; i<buf_size-1; i++)
{
memset(&temp, 0, sizeof(temp));
sprintf(temp, "%X:", (int)buf[i]);
strcat(result, temp);
}
memset(&temp, 0, sizeof(temp));
sprintf(temp, "%X", (int)buf[i]);
strcat(result, temp);
strcpy(buf, result);
}
Client side:
#define MAX_MESSAGE_SIZE 1024
// Implementation of client that will use the chat.
#include "client.h"
int main(int argc,char* argv[])
{
if(argc != 3) //check if user insert more then one argument to the program
{
printf("Usage client <host name> <port>\n‬‬");
fflush(stdout);
exit(-1);
}
/*!
========Client creation flow:========
1) create the socket
2) sendto (close the socket)
3) recvfrom (read from socket)
4) close the socket
*/
fprintf(stderr, "please enter something: \n");
//!------------------------------------- 1) create the socket-------------------------------------
int fd; //socket descriptor
if((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket");
exit(1);
}
struct sockaddr_in srv; //used by sendto()
srv.sin_family = AF_INET;
srand ( time(NULL) ); //new random seed
int rand_num = (rand() % 5) + atoi(argv[2]); //
srv.sin_port = htons(rand_num);
char *srv_name = argv[1];
struct hostent *hp; //ptr to host info for remote
hp = gethostbyname(srv_name);
if( hp == NULL)
{
herror("gethostbyname");
exit(-1);
}
srv.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr))->s_addr; //set IP Address to "srv_name"
char buf[MAX_MESSAGE_SIZE]; //used by read() & write()
int nbytes=0;
while(1)
{
//!------------------------------------- 2) sendto (close the socket)-------------------------------------
memset(&buf, 0, sizeof(buf)); //init buf
fgets(buf, sizeof(buf), stdin); //get input from user
if(strcmp(buf, "quit\n") == 0)
{
break;
}
if(!((strlen(buf) == 1) && (buf[1] == '\n')))
{
buf[strlen(buf)-1] = '\0';
}
//write_to_server(fd, buf, srv);
if ((nbytes = sendto(fd, buf, strlen(buf), MSG_DONTWAIT /* flags */, (struct sockaddr*) &srv, sizeof(srv)) < 0))
{
perror("sendto");
exit(1);
}
//!------------------------------------- 3) recvfrom (read from socket)-------------------------------------
memset(&buf, 0, sizeof(buf)); //init read_buf
//read_from_server(fd, buf);
if((nbytes = recvfrom(fd, buf, sizeof(buf), 0 /* flags */, 0, 0) < 0))
{
perror("recvfrom");
exit(1);
}
if( (errno == EAGAIN) || (errno == EWOULDBLOCK ) )
{
perror("EWOULDBLOCK");
exit(1);
}
printf("%s\n", buf); //print result to client
fflush(stdout);
}
//!------------------------------------- close the socket-------------------------------------
close(fd);
return 0;
}
I got it..
You need to use connect function from client and the "MSG_DONTWAIT" flag.
then when the client connect and you type anything he exit right away..
//!--------------- 2) connect to the server--------------------------
if(connect(fd, (struct sockaddr*) &srv, sizeof(srv)) < 0) //connect to server "srv_name"
{
perror("connect");
exit(-1);
}

Resources