I have the following libev code:
#include <ev.h>
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <string.h>
#include <stdlib.h>
#include <sys/un.h>
#include <netinet/in.h>
ev_io stdin_watcher;
static void cb(EV_P_ ev_io *w, int revents){
puts ("hello");
//read file here - suggestion due to Ioan
#define BUF_LEN 10
char buf[BUF_LEN];
memset(buf,0,BUF_LEN);
int byte_read;
while( (byte_read = recv(w->fd,buf,BUF_LEN-1,0)) > 0) {
printf("len: %i: %s",byte_read,buf);
memset(buf,0,BUF_LEN);
}
if(-1 == byte_read && EAGAIN != errno) {
perror("recv");
}
close(w->fd);
//ev_io_stop (EV_A_ w);
//ev_unloop (EV_A_ EVUNLOOP_ALL);
}
int main (void){
struct ev_loop *loop = ev_default_loop (0);
int len;
int sd;
sd=socket(AF_UNIX,SOCK_STREAM,0);
struct sockaddr_un address;
//memset(&address,0,sizeof(address));
address.sun_family=AF_UNIX;
strcpy(address.sun_path,"/tmp/mysocket");
unlink(address.sun_path);
len=strlen(address.sun_path)+sizeof(address.sun_family);
int x=bind(sd,(struct sockaddr*)&address,sizeof(address));
printf("%d\n",x);
listen(sd,5);
ev_io_init(&stdin_watcher,cb,sd,EV_READ);
ev_io_start(loop,&stdin_watcher);
ev_loop (loop, 0);
// unloop was called, so exit
return 0;
}
Everything works just fine (almost). Compile: gcc file.c -lev, and run ./a.out. Then write to the socket that ./a.out is listening on: echo "gobblydeegook" | nc -U /tmp/mysocket.
Hello appears on the console as expected.
But the program calls the event and then it keeps printing "hello" ad-infinitum! I want it to continue monitoring this unix socket for writes. How to do this?
The event gets called when there is data to be read on the socket. Since you aren't removing the data from the socket, just printing "hello", the event is called again for you to handle the data.
Related
I am working on a client/server c project in which I have a server and multiple clients sending requests to it. The application uses sockets for communication (AF_UNIX) and the whole connection part is fine (to say, using other methods rather than the select() one makes everything work just fine).
However, I am willing to use select() in order to notify the server of new events on the file descriptors in the set, which are the server socket fd and the single clients ones.
I have cleared the code from the parts which are not relevant to the issue I'm facing and now I only have the following:
The server, that initializes the socket communication and created a thread which has to perform the select() and accept() functions:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <pthread.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <string.h>
#include <utility.h>
void* handConn(void* address){
int fd_cli;
while(1){
printf("HANDLER: in handler\n");
if (select(max_fd+1, &rdset,NULL, NULL,NULL) == -1) {
perror("select");
exit(EXIT_FAILURE);
}
for(int i=0; i<=max_fd; i++){
if(FD_ISSET(i,&rdset) && i==sfd){
printf("new incoming connection to accept\n");
fd_cli=accept(sfd,NULL,NULL);
FD_SET(fd_cli,&rdset);
if(fd_cli>max_fd) max_fd=fd_cli;
}
else if(FD_ISSET(i,&rdset) && i!=sfd){
printf("event on old connection\n");
}
}
FD_ZERO(&rdset);
}
return (void*) NULL;
}
int main(void){
int i, fd_cli, tid;
max_fd=0;
struct sockaddr_un sa;
sa.sun_family=AF_UNIX;
strncpy(sa.sun_path,"tmp/sock", sizeof(sa.sun_path));
if((sfd=socket(AF_UNIX,SOCK_STREAM,0))<0){
perror("Server socket");
exit(EXIT_FAILURE);
}
if ( bind(sfd,(struct sockaddr *)&sa, sizeof(sa))<0){
perror("bind");
exit(EXIT_FAILURE);
}
listen(sfd,10); //10 is just for example purpose only
/* Init fd_set */
FD_ZERO(&rdset);
FD_SET(sfd, &rdset);
max_fd=sfd;
/*Handler thread creation */
if( pthread_create(&tid, NULL, handConn, (void*) &sa)<0){
perror("Handler thread creation");
exit(EXIT_FAILURE);
}
pthread_join(tid, NULL);
return 0;
}
The client, which performs the following (I removed the wrote-bytes control from the code because it is not relevant in this case):
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <utility.h>
int main(){
int fd_cli;
struct sockaddr_un sa;
sa.sun_family=AF_UNIX;
strncpy(sa.sun_path,"tmp/sock", sizeof(sa.sun_path));
if( (fd_cli = socket(AF_UNIX, SOCK_STREAM, 0))==-1){
perror("Client socket connection");
return -1;
}
while( (connect(fd_cli,(struct sockaddr*)&sa, sizeof(struct sockaddr_un))) == -1 ) {
if ( errno == ENOENT ) { sleep(1); }
else{
perror("Connect");
exit(EXIT_FAILURE);
}
}
printf("connected to server\n");
/*write something to server*/
int retvalue = write(sfd, writePointer, bytesLeft);
if(retvalue=0) /*handle...*/
if(retvalue==-1){
perror("writing");
return -1;
}
close(fd_cli);
return 0;
}
Last, the library in which are defined the variables used in the codes above:
#ifndef utility_h
#define utility_h
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
fd_set reset;
int sfd; //server fd
int max_fd;
The issue I am facing is that by executing even just one client, the select does not see the incoming connection.
What I would expect is the handler to print the following:
new incoming connection to accept
event on old connection
the first before doing the accept and the second when it intercepts the write.
The program, as it is don't print neither of those, so the handler can't even intercept a new incoming connection.
It just does nothing but getting stuck on select().
What might the issue be?
I'm having some trouble with my code. It should create a message queue and send a message, than wait some time for another program to receive that message and answer. The problem is, when I run it, I get an invalid argument both on the msgsnd and on the msgrcv.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/msg.h>
typedef struct my_msg{
long type;
char text[100];
char sqdr;
}message;
static void score(int messagge_id, char* A_B){
message send;
send.type=1;
strcpy(send.text, "Try to score");
send.sqdr = *A_B;
if((msgsnd(messagge_id, &send, sizeof(send), 0))<0)perror("Error msgsnd\n");
sleep(3);
if((msgrcv(messagge_id, &send, sizeof(send), 4, 0))==-1)perror("Error msgrcv 1\n");
int test=atoi(send.text);
printf("%d\n", test);
}
int main(){
int caso, key;
char team= 'A';
key=1234;
int msg_id=msgget(key, S_IRUSR|S_IWUSR);
printf("Try function score\n");
score(msg_id, &team);
printf("After score\n");
return 0;
}
You need to ensure that the message queue is created. You either use the key IPC_PRIVATE or you add IPC_CREAT to the flags. You also need to try to read the message correctly. You sent a 'type 1' message and attempted to read a 'type 4' message, so the read hangs.
This code also removes the message queue. That's not critical if it is a private queue (such queues are deleted when the program terminates), but it is important for queues using IPC_CREAT and a user-defined key. (I also changed the message text so that atoi() returned something more interesting — and convincing — than zero. The code also uses separate send and receive buffers so that we know the code is not cheating and reusing data already in the buffer.)
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>
#include <fcntl.h>
typedef struct my_msg
{
long type;
char text[100];
char sqdr;
} message;
static void score(int messagge_id)
{
message send;
message recv;
send.type = 1;
strcpy(send.text, "47 tries to score");
send.sqdr = 'A';
if ((msgsnd(messagge_id, &send, sizeof(send), 0)) < 0)
perror("Error msgsnd");
printf("Dozing...\n");
sleep(3);
printf("Unslumbering...\n");
if ((msgrcv(messagge_id, &recv, sizeof(recv), -4, 0)) == -1)
perror("Error msgrcv");
int test = atoi(recv.text);
printf("%d\n", test);
}
int main(void)
{
int key = 1234;
int flags = S_IRUSR|S_IWUSR|IPC_CREAT;
// int key = IPC_PRIVATE;
// int flags = S_IRUSR|S_IWUSR;
int msg_id = msgget(key, flags);
if (msg_id < 0)
perror("Error msgget");
else
{
printf("Try function score\n");
score(msg_id);
printf("After score\n");
if (msgctl(msg_id, IPC_RMID, 0) < 0)
perror("Error msgctl");
}
return 0;
}
Sample output:
Try function score
Dozing...
Unslumbering...
47
After score
There's a 3 second pause between 'Dozing' and 'Unslumbering', of course.
use like this:-
if((msgsnd(messagge_id, (void *)&send, sizeof(send), 0))<0)perror("Error msgsnd\n");
if((msgrcv(messagge_id, (void *)&send, sizeof(send), 4, 0))==-1)perror("Error msgrcv 1\n");
I have a program that prepares some configurations in one process and after that reads those configurations in the parent process. To sync them I'm using semaphores from semaphore.h library. But it seems that it's waiting forever in sem_wait even after I sem_post. It works after I do ctrl-z and fg though. Why is that? Can anyone tell me what's wrong with my code?
My OS is Lubuntu
Semaphore1.h
#ifndef _DNSS_H_
#define _DNSS_H_
#include <pthread.h>
#include <semaphore.h>
#include <time.h>
#include <sys/types.h>
typedef struct configs
{
int i;
sem_t sem;
} CONFIGS;
void init_config(CONFIGS *_configs);
//initiates the threadpool
int init_thread_pool(CONFIGS *configs);
#endif
Semaphore_1.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <semaphore.h>
#include <pthread.h>
#include "semaphore1.h"
void init_config(CONFIGS *_configs)
{
sem_init(&(_configs->sem),1,0); //Creaates a semaphore that is opened when the configs are read to shared memory
_configs->i=2;
fprintf(stderr, "Result of sem_post:%d\n", sem_post(&(_configs->sem)));
}
Semaphore_2.c
#include"semaphore1.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int init_thread_pool( CONFIGS *configs)
{
int aux;
fprintf(stderr, "Value of sem_wait():%d\n", sem_wait(&(configs->sem)));
printf("Threadpool initiated with %d threads!", configs->i);
return 1;
}
Semaphore_main.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include "semaphore1.h"
#include <sys/ipc.h>
#include <sys/shm.h>
int main(int argc, char *argv[])
{
pid_t config_pid; //will hold the configuration process id
int _shmid_configs;
CONFIGS *_configs;
_shmid_configs =shmget( IPC_PRIVATE,
sizeof(CONFIGS), IPC_CREAT|0666); //initializes the shared memory
if( _shmid_configs == -1)
{
perror("Error creating shared memory");
}
_configs=shmat(_shmid_configs, NULL,0); //maps the shared memory created to the processp and the config structure
if( _configs == ( CONFIGS*)-1)
{
perror("Error at shmat");
}
//initialization of the processes
config_pid = fork();
if( config_pid < 0)
{
perror("Failed creating configuration manager process");
}
else if( config_pid == 0)
{
init_config(_configs);
printf("Im config!\n");
return 0;
}
//CODE FOR THE gestor de pedidos
printf("right before the threadpool! Configs has a lmit of %d theads\n", _configs->i);
init_thread_pool(_configs);
printf("im parent and im out\n");
sem_destroy(&_configs->sem);
return 0;
}
Compiled with
gcc -g -pthread Semaphore_2.c Semaphore_main.c Semaphore_1.c -o deb
Output:
./deb
right before the threadpool! Configs has a lmit of 0 theads
Result of sem_post:0
Im config!
^Z
[1]+ Stopped ./deb
fg
./deb
Value of sem_wait():0
Threadpool initiated with 2 threads!im parent and im out
sem_init() should be called before fork().
In your current code it is possible for init_thread_pool(_configs); in the parent thread to be called before init_config(), that is you will wait on uninitialized semaphore. It is undefined behaviour.
I'm trying to setup a client/server in C. I establish the connection, then I want to send an username and a pwd to the server, and the server has to reply confirming that he has received the usr/pwd. The problem is that both server and client exit as soon as they meet the "write" or "read" function. What should I do?
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
#include <signal.h>
void main(){
int ds_sock;
struct sockaddr_in my_addr;
ds_sock=socket(AF_INET,SOCK_STREAM,0);
memset(&my_addr,0,sizeof(my_addr));
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(25000);
my_addr.sin_addr.s_addr=INADDR_ANY;
if(bind(ds_sock,(struct sockaddr *)&my_addr,sizeof(my_addr))<0){
printf("error in bind");
}
listen(ds_sock,2);
int ds_sock_acc;
struct sockaddr_in addr;
size_t sin_size = sizeof(struct sockaddr_in);
signal(SIGCHLD,SIG_IGN);
while(1){
if((ds_sock_acc=accept(ds_sock,(struct sockaddr *)&addr,&sin_size))<1){
printf("error accept");
}
printf("connected");
char usr[10];
read(ds_sock,usr,10);
char* confirm_usr;
confirm_usr="Username received";
write(ds_sock,confirm_usr,100);
char pwd[10];
read(ds_sock,pwd,10);
char* confirm_pwd;
confirm_pwd="Password received";
write(ds_sock,confirm_pwd,100);
}
}
client.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
void main(){
int ds_sock;
ds_sock = socket(AF_INET, SOCK_STREAM,0);
int ret;
struct sockaddr_in Eaddr;
Eaddr.sin_family = AF_INET;
Eaddr.sin_port = htons(25000);
Eaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
ret = connect(ds_sock,(struct sockaddr *)&Eaddr,sizeof(Eaddr));
if(ret==-1){
printf("error connect");
exit(EXIT_FAILURE);
}
printf("connect OK");
char usr[10];
printf("Insert username");
scanf("%s",usr);
char pwd[12];
printf("Insert password");
scanf("%s",pwd);
printf("%s",pwd);
write(ds_sock,usr,10);
char usr_reply[100];
read(ds_sock,usr_reply,100);
printf("%s",usr_reply);
write(ds_sock,pwd,12);
char pwd_reply[100];
read(ds_sock,pwd_reply,100);
printf("%s",pwd_reply);
}
While the first answer is pretty complete, I wanted to add the 141 error is a SIGPIPE error. (check this in linux manual)
You can strace your program to find the error code or implement errno and perror.
You're accessing out of bounds, thus triggering undefined behavior in your write() call:
char* confirm_usr;
confirm_usr="Username received";
write(ds_sock,confirm_usr,100);
You're asking write() to send 100 bytes, but you only provide a pointer to 18 bytes. Reading any more than 18 from that location triggers undefined behavior. It would make more sense to use strlen() to avoid hardcoding the length:
const char *confirm_usr = "Username received";
write(ds_sock, confirm_usr, strlen(confirm_usr) + 1);
I made it + 1 to actually send the terminating '\0'-character, otherwise the other end has no way of figuring out when the string ends.
Also, you must check the return value of lots of calls, I/O can and will fail and just must deal with that.
It's also pretty strange that it looks as if both server and client begin by doing a read(), and that the server does I/O on a socket different from ds_sock_acc.
I'm working on a problem wich implies a basic running server client(done one before). the problem is that I run server than I run client. My msg Que is created i nboth client takes my char as input sends it, i get the confirmation print but my server msgrcv isn't responding.
s.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <errno.h>
#include "struc.h"
int main(){
int qt;
struct msg m;
qt = msgget(1271,IPC_CREAT|IPC_EXCL|0600);
if(qt < 0){ perror("Error MSGGET()\n");}
printf("msg queue created!\n");
if(msgrcv(qt,&m,sizeof(struct msg),0,0)<0){
perror("Msg recive error");
}
printf("msg recived!\n");
msgctl(qt,IPC_RMID,NULL);
return 0;
}
c.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <errno.h>
#include "struc.h"
int main(){
int qt;
struct msg m;
qt = msgget(1271,0);
if(qt < 0){ perror("~~~ Error MSGGET()\n");}
printf("msg created!\n");
printf("Enter one char: !\n");
scanf("%c",&m.c);
msgsnd(qt, &m,sizeof(struct msg),0);
printf("msg sent!\n");
return 0;
}
struc.h
struct msg{
long mtype;
// matrix M;
char c;
};
(By creating the 3 files you cna test it yourself. Any idea is welcome maybe i missed something)
You should do this to verify that sending doesn't fail.
if(msgsnd(qt, &m,sizeof(struct msg),0)) < 0) {
perror("Msg send error");
}
You should also heed the docs for msgsnd:
The msgp argument is a pointer to caller-defined structure of the
following general form:
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
That is, you have to set the mtype in the message you send to be > 0. Currently it is uninitialized, so you should do:
m.mtype = 1;
if(msgsnd(qt, &m,sizeof(struct msg),0)) < 0) {
perror("Msg send error");
}