Newsgroup: it.comp.aiuto
Titolo: AIUTO SOCKET IN C

Vorrei sapere se per utilizzare le socket in C occorre linkare librerie
particolari e se per favore qualcuno mi spedisce un frammento minimo di
codice per un client che deve aprire una socket e collegarsi con un
server.
Un mio iniziale problema e' che alla linea
sd=socket(AF_INET,SOCK_STREAM, 0)
mi da' come errore che non ho definito AF_INET e SOCK_STREAM.
Grazie anticipato a tutti quelli che vorranno rispondere.
Ciao ciao Romina

 writes:
f> Vorrei sapere se per utilizzare le socket in C occorre linkare
f> librerie particolari
Sotto unix, occorre aggiungere -lsocket sulla linea di comando.
f>  Un mio iniziale problema e' che alla
f> linea sd=socket(AF_INET,SOCK_STREAM, 0) mi da' come errore che non
f> ho definito AF_INET e SOCK_STREAM.  Grazie anticipato a tutti
f> quelli che vorranno rispondere.
Hai incluso sia <sys/socket.h> che <sys/types.h> ?
Ecco qui un programmino che crea server e client. Unix. Si compila
tranquillo tranquillo con 
cc sox.c -o sox -lsocket
o   oooooo	Gian Uberto Lauri        "So, are you working on finding
      o    o	
sa...@maya.dei.unipd.it
   that bug *now* or leaving it until
     o o				  later?" - "Yes!" 
/*----------------------[taglia qui]-----------8<-----------*/
/ *
 * Esercizio dal corso di Sistemi Operativi
 *
 * D.E.I. Padova
 */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
server()
{
int sod, conn;  /* socket e connection descriptor */
char buf[256];
struct sockaddr mysad;  /* address del socket */
int i;
int flen;   /* lunghezza address ricevuto in accept */
    mysad.sa_family = AF_UNIX;
    strcpy(mysad.sa_data, "miost");
    if ((sod = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
        perror("server socket");
        exit(0);
    }
    /* bind nome, senza EOS */
    if(bind(sod, &mysad, sizeof(short)+strlen(mysad.sa_data)) == -1) {
        perror("server bind");
        exit(0);
    }
    printf("Server socket=%d bind \"miost\", ora listen\n", sod);
    if (listen(sod, 3) == -1) {
        shutdown(sod, 2);
        perror("server listen");
        exit(0);
    }
    /* lunghezza coda richieste unitaria */
    for(i=1; i<=5; i++) {
        printf("Server, ciclo %d esegue accept\n", i);
        if ((conn = accept(sod, &mysad, &flen)) == -1) {
            /* ascolta richieste di connessione: la chiamata
               restituisce l'indirizzo del client */
            shutdown(sod, 2);
            perror("server accept");
            exit(0);
        }
        printf("Server, arrivata richiesta\n");
        if (fork() == 0) {
            /* il figlio esegue il servizio */
            close(sod);    /* non serve al figlio */
            read(conn, buf, 256);
            printf("Server buf <%s>\n", buf);
            printf("Server, servizio terminato\n");
            exit(0);
        }
        /* padre */
        close(conn);    /* al padre non server */
        sleep(5);
        /* il padre si può far terminare con SIGINT */
    }    /* for */
    /* distruzione sockaddr come file */
    printf("*** Server finito, rimuove socket file\n");
    unlink("miost");
}
client(int cnt) {
int sod;  /* socket descriptor */
struct sockaddr mysad;  /* address del socket */
char buf[256];
    mysad.sa_family = AF_UNIX;
    strcpy(mysad.sa_data, "miost");
    printf("Client %d chiama socket\n", cnt);
    if ((sod = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
        perror("client socket");
        exit(0);
    }
    printf("Client %d sock = %d chiama connect\n", cnt, sod);
    /* connect fornendo nome, senza EOS */
    if (connect(sod, &mysad, sizeof(short)+strlen(mysad.sa_data))
      == -1) {
        perror("connect");
        exit(0);
    }
    sprintf(buf, "Sono client %d", cnt);
    write (sod, buf, strlen(buf)+1);
    printf("Client %d ha inviato, muore\n", cnt);
    shutdown(sod, 2);
    close(sod);
    exit(0);
}
main() {
int cnt = 1;
char s[20];
    printf("Main, crea server\n");
    if (fork()==0) {
        fclose(stdin);    /* non server al server */
        server();
        exit(0);    /* comunque il server non torna */
    }
    for (cnt=1; cnt<=5; cnt++) {
        printf("Main ciclo %d, battere return per nuovo client\n",
          cnt);
        gets(s);
        if (fork() == 0) {
            /* il figlio fa comunque exit */
            fclose(stdin);    /* non server al client */
            client(cnt);
        }
    }
    printf("++++ main finito\n");
}

Ecco qui un programmino che crea server e client. Unix. Si compila
Ed eccone uno che da` un esempio di client compilabile sia per
Unix, sia per Windows con Winsock -- il grosso dell'esempio
gestisce la connessione, compreso lookup del nome eccetera, e
un sorgentino separato resta responsabile della vera e propria
conversazione col server (l'esempiucolo qui offerto e` proprio
minimale, ma non e` difficile farne dei migliori -- praticamente
liberi dalle "problematiche di socket" in quanto tali).  Ho
anche un esempio analogo di server, se a qualcuno interessa
(il server non credo funzionerebbe su Win 3.1, ma su W/NT e
W95 funziona, l'ho testato).
-- cut: sockhead.h
#ifndef _SOCKHEAD_H
#define _SOCKHEAD_H
#include    <stdio.h>
#include    <stdlib.h>
#if WIN32
#    include <windows.h>
#    include <winsock.h>
#    define	soclose(fd)           closesocket(fd)
#else
#   include    <unistd.h>
#   include    <signal.h>
#   include    <sys/types.h>
#   include    <sys/time.h>
#   include    <sys/wait.h>
#   include    <time.h>
#   include    <errno.h>
#   include    <arpa/inet.h>
#   include    <sys/socket.h>
#   include	<netdb.h>
#   define	soclose(fd)           close(fd)
    typedef int SOCKET;
    typedef fd_set FDT;
#endif
#endif
-- cut: cliemain.c
/*
 * Generic program for TCP/IP clients -- (C) A. Martelli, al...@cirfid.unibo,it,
 * 1992-1996 -- use freely as long as credit is given -- NO WARRANTY!
 *
 * Port number is taken from environment variable TCP_PORT, else it
 * uses as default 6666.  Function cliedef() can change default port.
 *
 * Function client() is called with the socket handle of the already
 * connected socket and must handle all interactions, while main() as
 * present in this file only handles connections and disconnections.
 *
 * Flag: -v == verbose (by default, it's quiet)
 * Args: id of host to connect to
 * Other args if any are passed on to function client().
 */
#include "sockhead.h"
#define SELECT_TIMEOUT	30	/* seconds */
#define GENERIC_DEFAULT 6666    /* default for default tcp_port */
extern int client(SOCKET sockfd, char *pname, int nargs, char *argv[]);
extern void cliedef(u_short *defaultport);
SOCKET call_host_port(const char *host, int portnum);
u_short SERV_TCP_PORT=GENERIC_DEFAULT;      /* default, modifiable */
int v=0;
int startup_sockets();
int
main(int argc, char *argv[])
{
    SOCKET  	sockfd;
    const char *p;
    int rc;
    if(!startup_sockets()) return 1;
    if(argc>1 && strcmp(argv[1],"-v")==0) {v=1; --argc; ++argv;}
    if(argc<2) return 1;
    /*
     * Choice of TCP port number to use
     */
    cliedef(&SERV_TCP_PORT);
    if((p=getenv("TCP_PORT"))) {
        int specified=atoi(p);
        if(specified) SERV_TCP_PORT=specified;
    }
    /*
     * Open a TCP socket (internet, stream) to the host
     */
    sockfd = call_host_port(argv[1], SERV_TCP_PORT);
    if(!sockfd) return 1;
    rc=client(sockfd, argv[0], argc-1, argv+1);
    if(rc&&v) fprintf(stderr,"client: after connection, rc=%d\n",rc);
    soclose(sockfd);             /* close secondary socket */
    return 0;
}
/*
 * returns 0 on failure to start-up the socket system
 */
int
startup_sockets()
{
#if WIN32
WORD wVersionRequested; 
WSADATA wsaData; 
int err; 
wVersionRequested = MAKEWORD(1, 1); 
 
err = WSAStartup(wVersionRequested, &wsaData); 
 
if (err != 0) 
    /* Tell the user that we couldn't find a useable */ 
    /* winsock.dll.     */ 
    return 0; 
 
/* Confirm that the Windows Sockets DLL supports 1.1.*/ 
/* Note that if the DLL supports versions greater */ 
/* than 1.1 in addition to 1.1, it will still return */ 
/* 1.1 in wVersion since that is the version we */ 
/* requested. */ 
 
if ( LOBYTE( wsaData.wVersion ) != 1 || 
        HIBYTE( wsaData.wVersion ) != 1 ) { 
    /* Tell the user that we couldn't find a useable */ 
    /* winsock.dll. */ 
    WSACleanup(); 
    return 0; 
} 
/* The Windows Sockets DLL is acceptable. Proceed. */ 
    return 1;
#else
    return 1;
#endif
}
/*
 * given a host name (either name or internet address), return the
 * corresponding internet address as an unsigned long, or 0 if
 * the name/address given is invalid
 */
u_long
host_name_to_address(const char *host)
{
    u_long haddr;
    if(!host) return 0;
    if(isdigit(*host)) {
        haddr = inet_addr(host);
    } else {
        struct hostent  *hstp = gethostbyname(host);
        if(!hstp) return 0;
	haddr = **(u_long**)(hstp->h_addr_list);
    }
    return haddr;
}
/*
 * given a host name (either name or internet address) and port number,
 * return a stream socket opened to that host and port, or -1 for errors
 */
SOCKET
call_host_port(const char *host, int portnum)
{
    SOCKET sock;
    u_long hadr;
    struct sockaddr_in serv_addr;
    short sportnum=portnum;
    hadr = host_name_to_address(host);
    if(!hadr) return 0;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family      = AF_INET;
    serv_addr.sin_addr.s_addr = hadr;
    serv_addr.sin_port        = htons(sportnum);
    if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
	return 0;
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
	return 0;
    } else
	return sock;
}
-- cut: clieexam.c
/*
 * Generic program for TCP/IP clients -- (C) A. Martelli, al...@cirfid.unibo,it,
 * 1992-1996 -- use freely as long as credit is given -- NO WARRANTY!
 *
 * An example of the "client()" function called to implement a generic
 * TCP/IP client; its argument are the socket, already connected, and
 * the program's startup args, and it handles all interactions
 *
#include "sockhead.h"
/*
 * this gives you a chance to change the server's default port from 6666
 */
void
cliedef(u_short *defaultport)
{
    return;
}
/*
 * this sends to the server every line it gets from stdin, and
 * after each expects and prints to stdout a response from the
 * server
 */
int 
client(int sockfd, int nargs, char *argv[])
{
    char buf[300];
    int received;
    while(gets(buf)) {
	send(sockfd, buf, 1+strlen(buf), 0);
	received=recv(sockfd, buf, sizeof(buf), 0);
	buf[received]=0;
	printf("%s\n", buf);
    }
    return 0;
}
--
DISCLAIMER: these are MY personal opinions and viewpoints, NOT connected
in any way with my employer, nor any other organization or individual!
Email: 
mart...@cadlab.it
 -- Phone: +39 (51) 597 313  [Fax: 597 120]
Cad.Lab S.p.A., v. Ronzani 7/29, 40033 Casalecchio (BO), Italia

server.
sotto Unix
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
struct hostent *host
strunct sockaddr_in rem_indirizzo;
Il codice sara' piu' o meno cosi':
sd=socket(AF_INET,SOCK_STREAM, 0)
host=gethostbyname("
ftp.cnr.it
");	/* nome -> indirizzo Ip */
rem_indirizzo.sin_family=AF_INET;	/* un po' di conversioni ;-)
*/
rem_indirizzo.sin_addr.s_addr=((struct in_addr
*)(host->h_addr))->s_addr;
rem_indirizzo.sin_port=	/*il numero di porta*/
connect (sd, &rem_indirizzo,sizeof(struct sockaddr_in)) /*si
connette*/
dopodiche' devi solo legggere e scrivere con le normali read e write.
Alla fine chiudi con close.
Spero di esserti stato d'aiuto.
ciaociao, simone
I disclaim everything. (well, not really. my name should be correct)