私が実現するシステムはトークンのリングで構成されています(各トークンはckient-serverプロセスです)。C TCPソケット:ソケット上のread()は一時的に利用できないリソースを返す
私はそれが2つのプロセスを実行してテストしました。
関数serverMessageProcessor()
私はread()
を使用して(in)ソケットからメッセージのすべての部分を読み込み(処理した後)、(out)ソケットに別のメッセージを書き込む関数を呼び出します。
私はそれを行う最初の時間は、それがうまく機能し、二回目、私のreadMessage()
機能でread()
機能の一つは、他のプロセスにread: Success
(私が読んでエラーをキャッチするためにperror
を使用)とread: Resourse temporarily unavailable
を与えます。
コード内にデバッグ用のプリントがいくつかあります。 私があなたを助けてくれることを願っています。 ありがとうございます。 read()
戻っ0
が、それはソケットを意味
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h> //per le funzioni sui socket.
#include <arpa/inet.h> //per la funzione inet_aton().
#include <netinet/in.h> //per la struct sockaddr.
#include <sys/wait.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <ctype.h> //per la funzione isdigit().
#include <fcntl.h> //per rendere il socket bloccante o no.
#include <sys/select.h>
/* Error hendler */
void sys_error (const char *message) {
perror (message);
}
/* Connessione in ingresso */
int setUpConnectionIn(int port, int *sock_fd){
int sock_in;
struct sockaddr_in addr;
addr.sin_family = AF_INET; //Internet Address Family.
addr.sin_port=htons(port); //Local port.
addr.sin_addr.s_addr = htonl(INADDR_ANY); //Any incoming interface.
//Create socket for incoming connections.
if((sock_in = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
stampaStr("Errore: Creazione socket non riuscita.", 1);
return -1;
}
//Bind to the local address.
if(bind(sock_in, (struct sockaddr *) &addr, sizeof(addr)) < 0){
sys_error("Errore: impossibile assegnare l'indirizzo al socket.");
close(sock_in);
return -1;
}
//Mark the socket so it will listen for incoming connections.
if(listen(sock_in,5) < 0) {
sys_error("Errore: listen non riuscita.");
close(sock_in);
return -1;
}
*sock_fd = sock_in;
return 0;
}
/* Interfaccia Connessione in ingresso */
int setUpConnectionIn_2 (int sock_fd){
int connection_in;
if ((connection_in = accept(sock_fd, NULL, NULL)) < 0) {
sys_error ("Errore in funzione setUpConnectionIn_2");
return -1;
}
return connection_in;
}
/* Connessione in uscita */
int setUpConnectionOut (int *sock_fd, int connection_port, char *conn_addr){
int check;
struct sockaddr_in addr_out;
int sock_out;
addr_out.sin_family = AF_INET;
addr_out.sin_port = htons(connection_port);
if (inet_aton(conn_addr, &addr_out.sin_addr) < 0) {
sys_error ("Errore: inet_aton");
return -1;
}
if((sock_out = socket(PF_INET, SOCK_STREAM, 0))<0) {
sys_error("Errore: Creazione socket non riuscita.");
return -1;
}
stampaStr("In attesa di connessione alla stazione successiva..\n", 1);
while(connect(sock_out, (struct sockaddr *)&addr_out, sizeof(addr_out)) < 0);
*sock_fd = sock_out;
return 0;
}
int closed_ring = 0;
int readMessage (int *fd, unsigned char *cod, int *size, char **content) {
char *content_msg;
unsigned char cod_msg;
int size_msg;
int retval = fcntl(*fd, F_SETFL, fcntl(*fd, F_GETFL) | O_NONBLOCK);
printf ("readMessage - prima read\n");
if (read(*fd, &cod_msg, 1) == 0) {
sys_error ("read - cod_msg");
return -1;
}
if (read(*fd, &size_msg, 4) == 0) {
sys_error ("read - size_msg");
return -1;
}
*content = (char *)malloc((size_msg+1)*sizeof(char));
(*content)[size_msg+1] = '\0';
if (read(*fd, *content, size_msg) == 0) {
sys_error ("read - content_msg");
return -1;
}
retval = fcntl(*fd, F_SETFL, (fcntl(*fd, F_GETFL) | O_NONBLOCK) & (~O_NONBLOCK));
printf ("readMessage - dopo read\n");
printf ("(readMessage)cod: %c - size: %d - msg: %s\n", cod_msg, size_msg, *content);
*cod = cod_msg;
*size = size_msg;
//content = (char *)malloc(size_msg*sizeof(char));
//memcpy(content, content_msg, strlen(content_msg));
//content = content_msg;
printf ("content: %s\n", *content);
return 0;
}
int buildMessage (char **new_msg, unsigned char cod, int size, char *content) {
int msg_len = size+6;
*new_msg = (char *)malloc(msg_len*sizeof(char));
(*new_msg)[0] = cod;
memcpy (((*new_msg)+1), &size, 4);
memcpy (((*new_msg)+5), content, size);
(*new_msg)[msg_len] = '\0';
//new_msg = msg;
return strlen (*new_msg);
}
int serverMessageProcessor (int *fd_in, int *out_fds) {
char *new_msg;
char *content_msg;
unsigned char cod_msg = 100;
int size_msg;
int msg_length;
char *tmp_PID_str;
uint64_t myPID;
uint64_t tempPID;
int fd;
if (readMessage (fd_in, &cod_msg, &size_msg, &content_msg) < 0) {
sys_error ("readMessage");
return -1;
}
printf ("(serverMessageProcessor) cod: %c - size: %d - msg: %s\n", cod_msg, size_msg, content_msg);
printf ("serverMessageProcessor - prima switch\n");
switch (cod_msg) {
case ('1'): {
fd = 0;
if ((myPID = getpid()) < 0) {
sys_error ("getpid");
return -1;
}
tmp_PID_str = (char *)malloc((size_msg+1)*sizeof(char));
tmp_PID_str[size_msg+1] = '\0';
printf ("serverMessageProcessor - prima memcpy(myPID) PID: %ld\n", myPID);
memcpy (tmp_PID_str, &myPID, sizeof(uint64_t));
printf ("serverMessageProcessor - dopo memcpy(myPID)\n");
if (strcmp (content_msg, tmp_PID_str) == 0) {
printf ("serverMessageProcessor - dopo strcmp TRUE (myPID, tempPID)\n");
closed_ring = 1;
} else {
//new_msg = (char *)malloc(size_msg+6)*sizeof(char));
printf ("serverMessageProcessor - dopo strcmp FALSE (myPID, tempPID)\n");
//msg_length = buildMessage (&new_msg, cod_msg, size_msg, content_msg);
msg_length = size_msg+6;
new_msg = (char *)malloc(msg_length*sizeof(char));
new_msg[0] = cod_msg;
memcpy (new_msg+1, &size_msg, 4);
memcpy (new_msg+5, content_msg, size_msg);
new_msg[msg_length] = '\0';
printf ("serverMessageProcessor - dopo buildMessage: %s\n", new_msg);
printf ("(serverMessageProcessor) cod: %c - size: %d - msg: %s\n", cod_msg, size_msg, content_msg);
if (write (out_fds[fd], &cod_msg, 1) < 0) {
sys_error ("write");
return -1;
}
if (write (out_fds[fd], &size_msg, 4) < 0) {
sys_error ("write");
return -1;
}
if (write (out_fds[fd], content_msg, size_msg) < 0) {
sys_error ("write");
return -1;
}
printf ("serverMessageProcessor - dopo write\n");
}
printf ("serverMessageProcessor - fuori if strcmp(myPID, tempPID)\n");
}
}
}
int main (int argc, char *argv[]) {
int listen_port, connection_port;
int connection;
int check = -1;
char *conn_addr;
char inter_lv = 'a';
int sock_in; //socket descriptor for reading.
int sock_out; //socket descriptor for writing.
struct sockaddr_in addr_in;
struct sockaddr_in addr_out;
int connection_flag = 0;
int out_fds[3];
/********************* VARIABILI GESTIONE MESSAGGI ************************/
char *new_msg = NULL;
char *content_msg = NULL;
unsigned char cod_msg;
int size_msg;
int msg_len;
uint64_t tempPID;
uint64_t myPID;
/**************************************************************************/
/********************** VARIABILI GESTIONE SOTTOPROCESSI ******************/
int pipe_IN[2];
int pipe_OUT[2];
int pipe_CLIENT[2];
int pid_client;
/**************************************************************************/
/***************************** VARIABILI PER SELECT SYSCALL ***************/
fd_set rfds;
struct timeval tv;
int retval;
/**************************************************************************/
if(readIntFromString(0, &listen_port, argv[1]) < 0){
printf("Invalid value of listen_port\n");
return -1;
}
if(listen_port >= 0 && listen_port <= 1023){
printf("Insert a port in range 0-1023\n");
return -1;
}
if(listen_port >= 49152){
printf("Insert a port not higher than 49152\n");
return -1;
}
if(readIntFromString(0, &connection_port, argv[2]) < 0){
printf("Invalid value of connection_port\n");
return -1;
}
if(connection_port >= 0 && connection_port <= 1023){
printf("Insert a port in range 0-1023\n");
return -1;
}
if(connection_port >= 49152){
printf("Insert a port not higher than 49152\n");
return -1;
}
conn_addr = argv[3];
if((toupper(argv[4][0]) == 'S' || toupper(argv[4][0]) == 'N') && argv[4][1] == '\0'){
inter_lv = toupper(argv[4][0]);
}else{
printf("Invalid Interactivity Level\n");
return -1;
}
/*********************** Circuit Building **************************/
if(setUpConnectionIn(listen_port, &sock_in) < 0) {
sys_error ("Errore in funzione: setUpConnectionIn");
return -1;
}
if (setUpConnectionOut (&sock_out, connection_port, conn_addr) < 0) {
sys_error ("Errore in funzione setUpConnectionOut");
return -1;
}
printf ("-------------out-connected-------------\n");
if ((connection = setUpConnectionIn_2 (sock_in)) < 0) {
sys_error ("Errore in funzione setUpConnectionIn_2");
return -1;
}
printf ("-------------in-connected--------------\n");
/**********************************************************************/
/* Controlla connection (socket in entrata) per vedere se è pronto per operazioni di I/O */
//retval = fcntl(connection, F_SETFL, fcntl(connection, F_GETFL) | O_NONBLOCK);
FD_ZERO(&rfds);
FD_SET(connection, &rfds);
out_fds[0] = sock_out;
/* Attende 5 secondi */
tv.tv_sec = 5;
tv.tv_usec = 0;
while (closed_ring == 0) {
if (connection_flag == 0) {
if ((myPID = getpid()) < 0) {
sys_error ("getpid");
return -1;
}
size_msg = sizeof(uint64_t);
msg_len = size_msg+6;
new_msg = (char*)malloc(msg_len*sizeof(char));
new_msg[0] = '1';
memcpy(new_msg+1, &size_msg, 4);
memcpy(new_msg+5, &myPID, size_msg);
new_msg[msg_len] = '\0';
printf ("(MAIN) myPID: %ld - cod: %c - size: %d - msg: %s\n", myPID, new_msg[0], size_msg, &(new_msg[5]));
if (write (out_fds[0], new_msg, msg_len) < 0) {
sys_error ("write");
return -1;
}
printf ("Message 1 (ring closing) sent: %s\n", new_msg);
connection_flag = 1;
}
retval = select(connection+1, &rfds, NULL, NULL, &tv);
if (retval == -1) {
sys_error ("select");
return -1;
} else if (retval) {
stampaStr("Available data on (in)socket\n", 1); /* FD_ISSET(0, &rfds) avrà valore TRUE */
/*************** DEBUG ************************
if (read (connection, &cod_msg, 1) == 0) {
sys_error ("read - main");
return -1;
} else {
printf ("read - main: %c\n", cod_msg);
}
**********************************************/
if (serverMessageProcessor (&connection, out_fds) < 0) {
sys_error ("serverMessageProcessor");
return -1;
}
} else {
stampaStr("None message in entry\n", 1);
char c = getchar();
fflush(stdin);
}
}
/* Creazione sottoprocesso per gestione connessioni con Client per iscrizione auto */
if (pipe(pipe_CLIENT) < 0) {
sys_error ("pipe_client");
return -1;
}
if ((pid_client = fork()) < 0) {
sys_error ("fork_client");
return -1;
} else if (pid_client == 0) { /* Processo figlio - accetta connessioni da Client */
printf("Subprocess to manage client(s) connection\n");
//while (1);
} else { /* Processo Padre */
printf("Parent process\n");
}
return 0;
}
これは、ソケットが閉じられたことを意味しません。これは、ピアがきれいに切断されたことを意味します。このアプリケーションではソケットを閉じておく必要があります。他の 'select()'コール、別のループなどでシミュレートしようとするのではなく、ブロッキングモードを使用するのがより簡単な解決策です。 – EJP
コードを修正しましたが、Resource一時的に利用できないエラーが返されます。成功 "エラー"ではありません。 – user7836391
@EJP私はそれが反対側によって閉鎖されていると言っていました。 – Barmar