Accept: socket operation on non-socket
2 participants
Page 1 sur 1
Accept: socket operation on non-socket
Bonjour,
Contexte :
Dans un but éducatif, je tente de développer une petite application console (sous linux) permettant d'envoyer des fichiers par le réseau internet.
Problème:
Du côté serveur de l'application. Je souhaite que mon programme permette à l'utilisateur d' entrer des commandes sans interruption, même pendant l'appel à une fonction accept(). J'ai donc décidé de lancer la fonction accept() dans un thread, en envoyant également au thread les informations nécessaires à la fonction. Extrait :
Cependant, lors du lancement du programme, après avoir lancé le serveur ( taper "start server" ), la fonction accept() renvoie une erreur que je n'arrive pas à comprendre.
J'ai googlisé un long moment en vain, j'ai cogité longtemps an vain également, j'ai vérifié les retours des fonctions socket(), listen(), bind() ... je ne sais plus quoi faire.
J'ai pensé finallement qu'il fallait initialiser les structures SOCKADDR_IN sin et csin, mais sous linux, la syntaxe trouvée sur ce site ne semble pas acceptée (ou alors par le compilateur), à savoir :
struct sockaddr_in machin = {0}; // renvoie une erreur de compilation
Veuillez trouver ci-dessous mon code complet en un fichier :
Woups, désolé je viens de m'apercevoir que le code n'est pas portable, j'ai écrit sous linux ...
Quelqu'un pourrait-il m'aider néanmoins ?
Contexte :
Dans un but éducatif, je tente de développer une petite application console (sous linux) permettant d'envoyer des fichiers par le réseau internet.
Problème:
Du côté serveur de l'application. Je souhaite que mon programme permette à l'utilisateur d' entrer des commandes sans interruption, même pendant l'appel à une fonction accept(). J'ai donc décidé de lancer la fonction accept() dans un thread, en envoyant également au thread les informations nécessaires à la fonction. Extrait :
- Code:
typedef struct {
int sock; // socket serveur
int *csock; // tableau de sockets client
struct sockaddr_in csin;
unsigned int crecsize;
} S_socket;
static void*
server_first_thread(void *data)
{
int free_number = 0; // pour trouver un socket libre dans le tableau de sockets clients
S_socket *socket_data = (S_socket *) data; // pour récuprer notre structure passée en argument
unsigned int crecsize = (unsigned int) sizeof socket_data->csin;
while (1) {
free_number = find_unused_socket_number(socket_data->csock);
/* si on ne trouve pas de socket libre */
if (free_number == -1) {
pthread_exit(NULL);
}
/* ACCEPT ----------------- */
socket_data->csock[free_number] = accept(socket_data->sock,
(struct sockaddr *) &socket_data->csin,
&crecsize);
if (socket_data->csock[free_number] != INVALID_SOCKET) {
printf(" -->One client connected from %s\n",
inet_ntoa(socket_data->csin.sin_addr) );
}
else {
perror ("accept");
break;
}
}
return (void *) NULL;
}
Cependant, lors du lancement du programme, après avoir lancé le serveur ( taper "start server" ), la fonction accept() renvoie une erreur que je n'arrive pas à comprendre.
J'ai googlisé un long moment en vain, j'ai cogité longtemps an vain également, j'ai vérifié les retours des fonctions socket(), listen(), bind() ... je ne sais plus quoi faire.
J'ai pensé finallement qu'il fallait initialiser les structures SOCKADDR_IN sin et csin, mais sous linux, la syntaxe trouvée sur ce site ne semble pas acceptée (ou alors par le compilateur), à savoir :
struct sockaddr_in machin = {0}; // renvoie une erreur de compilation
Veuillez trouver ci-dessous mon code complet en un fichier :
- Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <strings.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define PORT 6000
#define MAX_CONNEC 5
enum {EXIT, HELP, CONNECT, START_SERVER, START_CLIENT};
typedef struct {
int sock;
int *csock;
struct sockaddr_in csin;
unsigned int crecsize;
} S_socket;
void
clean_buffer (char *chaine) {
char *p = strchr(chaine, '\n');
int c;
if (p) {
*p = 0;
}
else {
while ((c = getchar()) != '\n' && c != EOF) {}
}
}
int
client_start (const char **commands) {
char chaine[32] = {0}; // stores user's commands
int my_error = 0;
while (1) {
printf("client >");
fgets(chaine, sizeof(chaine), stdin);
clean_buffer(chaine);
if (my_error != 0) {
break;
}
else if ( strcmp(chaine, commands[EXIT]) == 0 ) {
break;
}
else if (strcmp(chaine, commands[CONNECT]) == 0) {
puts(" Starting client");
//error = ;
}
else if (strcmp(chaine, commands[HELP]) == 0) {
puts(" Available commands : \n exit\n connect");
}
}
return my_error;
}
/* returns a freed place number from a socket(int) array */
int
find_unused_socket_number(int *array) {
int retval = -1;
for(int i = 0; i<7; i++) {
if(array[i] == 0) {
retval = i;
break;
}
}
return retval;
}
static void*
server_first_thread(void *data)
{
int free_number = 0;
S_socket *socket_data = (S_socket *) data;
unsigned int crecsize = (unsigned int) sizeof socket_data->csin;
while (1) {
free_number = find_unused_socket_number(socket_data->csock);
if (free_number == -1) {
pthread_exit(NULL);
}
/* ACCEPT ----------------- */
socket_data->csock[free_number] = accept(socket_data->sock,
(struct sockaddr *) &socket_data->csin,
&crecsize);
if (socket_data->csock[free_number] != INVALID_SOCKET) {
printf(" -->One client connected from %s\n",
inet_ntoa(socket_data->csin.sin_addr) );
}
else {
perror ("accept");
break;
}
}
return (void *) NULL;
}
int
server_start (const char **commands) {
char chaine[32] = {0}; // stores user's commands
int my_error = 0;
//char *buffer = "bonjour";
pthread_t t1;
/* server side */
struct sockaddr_in sin;
int sock = 0;
unsigned int recsize = (unsigned int) sizeof sin;
/* client side */
struct sockaddr_in csin;
int csock[7] = {0};
// unsigned int crecsize = (unsigned int) sizeof csin;
S_socket send_to_thread = {
.sock = sock,
.csock = csock,
.csin = csin
};
int sock_err;
sock = socket(AF_INET, SOCK_STREAM, 0);
if( sock >= 0 )
{
printf(" -->Socket %d is now opened in TCP/IP mode\n", sock);
sin.sin_addr.s_addr = inet_addr("127.0.0.1"); /* htonl(INADDR_ANY); OR inet_addr("127.0.0.1"); */
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sock_err = bind(sock, (struct sockaddr *) &sin, recsize);
if(sock_err >= 0)
{
sock_err = listen(sock, MAX_CONNEC);
printf(" -->Port %d configured\n", PORT);
if(sock_err >= 0)
{
printf(" -->Waiting for a client to connect to port %d...\n", PORT);
/* accept() thread */
pthread_create (&t1, NULL, server_first_thread, &send_to_thread);
/*--------------------------------------------------------------------------------------------*/
/* user interface */
while (1) {
printf("server >");
fgets(chaine, sizeof(chaine), stdin);
clean_buffer(chaine);
if (my_error != 0) {
break;
}
else if ( strcmp(chaine, commands[EXIT]) == 0 ) {
pthread_cancel(t1);
break;
}
else if (strcmp(chaine, commands[HELP]) == 0) {
puts(" Available commands : \n exit");
}
}
/*--------------------------------------------------------------------------------------------*/
/*sock_err = send(csock, buffer, strlen(buffer), 0);
if ( sock_err != SOCKET_ERROR ) {
printf(" -->Sending : SUCCESS\n");
}
else
printf(" -->Sending ERROR ! \n");*/
for (int i = 0; i<7; i++) {
shutdown(csock[i], SHUT_RDWR);
}
}
else
perror("listen");
}
else
perror("bind");
puts(" -->Client socket closing");
for (int i = 0; i<7; i++) {
shutdown(csock[i], SHUT_RDWR);
}
puts(" -->Serveur socket closing");
shutdown(sock, SHUT_RDWR);
puts(" -->Shutdown complete");
}
else {
my_error = -1;
}
return my_error;
}
int
main () {
char chaine[32] = {0}; // stores user's commands
const char *commands[] =
{"exit", "help", "connect", "start server", "start client"};
int error = 0;
while (1) {
printf("main >");
fgets(chaine, sizeof(chaine), stdin);
clean_buffer(chaine);
if (error != 0) {
puts(" ---* Error detected! Exiting now *---");
exit(error);
}
else if ( strcmp(chaine, commands[EXIT]) == 0 ) {
break;
}
else if (strcmp(chaine, commands[START_CLIENT]) == 0) {
puts(" Starting client");
error = client_start(commands);
}
else if (strcmp(chaine, commands[START_SERVER]) == 0) {
puts(" Starting server");
error = server_start(commands);
}
else if (strcmp(chaine, commands[HELP]) == 0) {
puts(" Available commands : \n exit\n start server\n start client");
}
for (int i = 0; i<32; i++) {
chaine[i] = 0;
}
}
return 0;
}
Woups, désolé je viens de m'apercevoir que le code n'est pas portable, j'ai écrit sous linux ...
Quelqu'un pourrait-il m'aider néanmoins ?
Mr_belette- Messages : 6
Date d'inscription : 12/07/2009
Age : 41
Localisation : Poitiers
Re: Accept: socket operation on non-socket
Avec ce code :
J'obtiens (windows) :
J'ajoute une trace pour voir ce qui se passe :
Ne rien supposer, ne faire confiance qu'en ce qu'on voit...
- Code:
#ifdef __cplusplus
#error Be sure you are using a C compiler...
#endif
#if defined (WIN32) || defined (_WIN32)
#include <winsock2.h>
enum
{
SHUT_RD = 0, /* No more receptions. */
#define SHUT_RD SHUT_RD
SHUT_WR, /* No more transmissions. */
#define SHUT_WR SHUT_WR
SHUT_RDWR /* No more receptions or transmissions. */
#define SHUT_RDWR SHUT_RDWR
};
#elif defined (linux) || defined (_POSIX_VERSION) || defined (_POSIX2_C_VERSION)\
|| defined (_XOPEN_VERSION)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* close */
#include <unistd.h>
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(s) close (s)
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
#else
#error not defined for this platform
#endif
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
/* macros ============================================================== */
#define PORT 6000
#define MAX_CONNEC 5
#define NELEM(a) (sizeof(a)/sizeof*(a))
/* constants =========================================================== */
enum
{ EXIT, HELP, CONNECT, START_SERVER, START_CLIENT };
/* types =============================================================== */
typedef struct
{
int sock;
int *csock;
struct sockaddr_in csin;
unsigned int crecsize;
}
S_socket;
/* structures ========================================================== */
/* private data ======================================================== */
/* private functions =================================================== */
/* ---------------------------------------------------------------------
--------------------------------------------------------------------- */
static void psock_perror (char const *cmt)
{
#if defined (WIN32) || defined (_WIN32)
fprintf (stderr, "%s: ", cmt);
{
DWORD err = WSAGetLastError ();
wchar_t msg[1024];
FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0,
msg, NELEM (msg), NULL);
fwprintf (stderr, L"%s\n", msg);
}
#elif defined (linux) || defined (_POSIX_VERSION) || defined (_POSIX2_C_VERSION)\
|| defined (_XOPEN_VERSION)
perror (cmt);
#else
#error not defined for this platform
#endif
}
static void clean_buffer (char *chaine)
{
char *p = strchr (chaine, '\n');
int c;
if (p)
{
*p = 0;
}
else
{
while ((c = getchar ()) != '\n' && c != EOF)
{
}
}
}
static int client_start (const char **commands)
{
/* stores user's commands */
char chaine[32] = { 0 };
int my_error = 0;
while (1)
{
printf ("client >");
fgets (chaine, sizeof (chaine), stdin);
clean_buffer (chaine);
if (my_error != 0)
{
break;
}
else if (strcmp (chaine, commands[EXIT]) == 0)
{
break;
}
else if (strcmp (chaine, commands[CONNECT]) == 0)
{
puts (" Starting client");
/* error = ; */
}
else if (strcmp (chaine, commands[HELP]) == 0)
{
puts (" Available commands : \n exit\n connect");
}
}
return my_error;
}
/* returns a freed place number from a socket(int) array */
static int find_unused_socket_number (int *array)
{
int retval = -1;
int i;
for (i = 0; i < 7; i++)
{
if (array[i] == 0)
{
retval = i;
break;
}
}
return retval;
}
static void *server_first_thread (void *data)
{
int free_number = 0;
S_socket *socket_data = (S_socket *) data;
unsigned int crecsize = (unsigned int) sizeof socket_data->csin;
while (1)
{
free_number = find_unused_socket_number (socket_data->csock);
if (free_number == -1)
{
pthread_exit (NULL);
}
/* ACCEPT ----------------- */
socket_data->csock[free_number] = accept (socket_data->sock,
(struct sockaddr *)
&socket_data->csin,
&crecsize);
if (socket_data->csock[free_number] != INVALID_SOCKET)
{
printf (" -->One client connected from %s\n",
inet_ntoa (socket_data->csin.sin_addr));
}
else
{
psock_perror ("accept");
break;
}
}
return (void *) NULL;
}
static int server_start (const char **commands)
{
/* stores user's commands */
char chaine[32] = { 0 };
int my_error = 0;
/* char *buffer = "bonjour"; */
pthread_t t1;
/* server side */
struct sockaddr_in sin;
int sock = 0;
unsigned int recsize = (unsigned int) sizeof sin;
/* client side */
struct sockaddr_in csin;
int csock[7] = { 0 };
/* unsigned int crecsize = (unsigned int) sizeof csin; */
S_socket send_to_thread = { 0 };
int sock_err;
send_to_thread.sock = sock;
send_to_thread.csock = csock;
send_to_thread.csin = csin;
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock >= 0)
{
printf (" -->Socket %d is now opened in TCP/IP mode\n", sock);
/* htonl(INADDR_ANY); OR inet_addr("127.0.0.1"); */
sin.sin_addr.s_addr = inet_addr ("127.0.0.1");
sin.sin_family = AF_INET;
sin.sin_port = htons (PORT);
sock_err = bind (sock, (struct sockaddr *) &sin, recsize);
if (sock_err >= 0)
{
sock_err = listen (sock, MAX_CONNEC);
printf (" -->Port %d configured\n", PORT);
if (sock_err >= 0)
{
printf (" -->Waiting for a client to connect to port %d...\n",
PORT);
/* accept() thread */
pthread_create (&t1, NULL, server_first_thread, &send_to_thread);
/*--------------------------------------------------------------------------------------------*/
/* user interface */
while (1)
{
printf ("server >");
fgets (chaine, sizeof (chaine), stdin);
clean_buffer (chaine);
if (my_error != 0)
{
break;
}
else if (strcmp (chaine, commands[EXIT]) == 0)
{
pthread_cancel (t1);
break;
}
else if (strcmp (chaine, commands[HELP]) == 0)
{
puts (" Available commands : \n exit");
}
}
/*--------------------------------------------------------------------------------------------*/
/*sock_err = send(csock, buffer, strlen(buffer), 0);
if ( sock_err != SOCKET_ERROR ) {
printf(" -->Sending : SUCCESS\n");
}
else
printf(" -->Sending ERROR ! \n");*/
{
int i;
for (i = 0; i < 7; i++)
{
shutdown (csock[i], SHUT_RDWR);
}
}
}
else
psock_perror ("listen");
}
else
psock_perror ("bind");
puts (" -->Client socket closing");
{
int i;
for (i = 0; i < 7; i++)
{
shutdown (csock[i], SHUT_RDWR);
}
}
puts (" -->Serveur socket closing");
shutdown (sock, SHUT_RDWR);
puts (" -->Shutdown complete");
}
else
{
my_error = -1;
}
return my_error;
}
static int app (void)
{
/* stores user's commands */
char chaine[32] = { 0 };
const char *commands[] =
{ "exit", "help", "connect", "start server", "start client" };
int error = 0;
while (1)
{
printf ("main >");
fgets (chaine, sizeof (chaine), stdin);
clean_buffer (chaine);
if (error != 0)
{
puts (" ---* Error detected! Exiting now *---");
exit (error);
}
else if (strcmp (chaine, commands[EXIT]) == 0)
{
break;
}
else if (strcmp (chaine, commands[START_CLIENT]) == 0)
{
puts (" Starting client");
error = client_start (commands);
}
else if (strcmp (chaine, commands[START_SERVER]) == 0)
{
puts (" Starting server");
error = server_start (commands);
}
else if (strcmp (chaine, commands[HELP]) == 0)
{
puts (" Available commands : \n exit\n start server\n start client");
}
{
int i;
for (i = 0; i < 32; i++)
{
chaine[i] = 0;
}
}
}
return 0;
}
/* entry point ========================================================= */
/* ---------------------------------------------------------------------
--------------------------------------------------------------------- */
int main (void)
{
int ret;
#if defined (WIN32) || defined (_WIN32)
WSADATA wsa_data;
int err = WSAStartup (MAKEWORD (2, 2), &wsa_data);
if (!err)
{
puts ("WIN: winsock2: OK");
}
#else
int err = 0;
{
#endif
if (!err)
{
app ();
}
#if defined (WIN32) || defined (_WIN32)
WSACleanup ();
#else
}
#endif
if (err)
{
ret = EXIT_FAILURE;
}
else
{
ret = EXIT_SUCCESS;
}
return ret;
}
J'obtiens (windows) :
- Code:
WIN: winsock2: OK
main >start server
Starting server
-->Socket 76 is now opened in TCP/IP mode
-->Port 6000 configured
-->Waiting for a client to connect to port 6000...
server >accept: Une opÚration a ÚtÚ tentÚe sur autre chose qu'un socket.
server >exit
-->Client socket closing
-->Serveur socket closing
-->Shutdown complete
main >exit
Process returned 0 (0x0) execution time : 30.594 s
Press any key to continue.
J'ajoute une trace pour voir ce qui se passe :
- Code:
/* ACCEPT ----------------- */
/* -ed- trace : */
printf("SRV: socket_data->sock = %d\n", socket_data->sock);
socket_data->csock[free_number] = accept (socket_data->sock,
(struct sockaddr *)
&socket_data->csin,
&crecsize);
- Code:
WIN: winsock2: OK
main >start server
Starting server
-->Socket 76 is now opened in TCP/IP mode
-->Port 6000 configured
-->Waiting for a client to connect to port 6000...
server >SRV: socket_data->sock = 0
accept: Une opÚration a ÚtÚ tentÚe sur autre chose qu'un socket.
<...>
- Code:
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock >= 0)
{
printf (" -->Socket %d is now opened in TCP/IP mode\n", sock);
/* -ed- correction */
send_to_thread.sock = sock;
- Code:
WIN: winsock2: OK
main >start server
Starting server
-->Socket 76 is now opened in TCP/IP mode
-->Port 6000 configured
-->Waiting for a client to connect to port 6000...
server >SRV: socket_data->sock = 76
-->One client connected from 127.0.0.1
SRV: socket_data->sock = 76
server >exit
-->Client socket closing
-->Serveur socket closing
-->Shutdown complete
main >exit
Process returned 0 (0x0) execution time : 42.152 s
Press any key to continue.
Ne rien supposer, ne faire confiance qu'en ce qu'on voit...
Merci
En effet, je vois : j'avais passé à ma structure de données un socket pas encore initialisé avec la fonction socket()...
Que dire, on imagine toujours que ces défaillances d'attention sont derrière soit, mais non.
Merci beaucoup de votre attention !
Bonne journée à tous,
Matthieu
Que dire, on imagine toujours que ces défaillances d'attention sont derrière soit, mais non.
Merci beaucoup de votre attention !
Bonne journée à tous,
Matthieu
Mr_belette- Messages : 6
Date d'inscription : 12/07/2009
Age : 41
Localisation : Poitiers
Page 1 sur 1
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum
|
|