2014-01-15 42 views
0

所以這裏是使用Linux GCC的SCTP回聲服務器程序的代碼:SCTP回聲服務器代碼:字節順序警告消息

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <sctp.h> 
#include <sctp/syscalls.h> 
#include <netdb.h> 
#include <linux/signal.h> 

#define PORT "5000" // the port users will be connecting to 


#define BUFLEN 1024 

/* 
* Given an event notification, print out what it is. 
*/ 
static void handle_event(void *buf) 
{ 

    char addrbuf[INET6_ADDRSTRLEN]; 
    const char *ap; 
    struct sockaddr_in *sin; 
    struct sockaddr_in6 *sin6; 
    struct sctp_assoc_change *sac; 
    struct sctp_send_failed *ssf; 
    struct sctp_paddr_change *spc; 
    struct sctp_remote_error *sre; 
    union sctp_notification *snp = (union sctp_notification*)buf; 

    switch (snp->sn_header.sn_type) { 
    case SCTP_ASSOC_CHANGE: 
     sac = &snp->sn_assoc_change; 
     printf("^^^ assoc_change: state=%hu, error=%hu, instr=%hu " 
      "outstr=%hu\n", sac->sac_state, sac->sac_error, 
      sac->sac_inbound_streams, sac->sac_outbound_streams); 
     break; 
    case SCTP_SEND_FAILED: 
     ssf = &snp->sn_send_failed; 
     printf("^^^ sendfailed: len=%hu err=%d\n", ssf->ssf_length, 
      ssf->ssf_error); 
     break; 
    case SCTP_PEER_ADDR_CHANGE: 
     spc = &snp->sn_paddr_change; 
     if (spc->spc_aaddr.ss_family == AF_INET) { 
      sin = (struct sockaddr_in *)&spc->spc_aaddr; 
      ap = inet_ntop(AF_INET, &sin->sin_addr, addrbuf, 
       INET6_ADDRSTRLEN); 
     } else { 
      sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr; 
      ap = inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, 
       INET6_ADDRSTRLEN); 
     } 
     printf("^^^ intf_change: %s state=%d, error=%d\n", ap, 
      spc->spc_state, spc->spc_error); 
     break; 
    case SCTP_REMOTE_ERROR: 
     sre = &snp->sn_remote_error; 
     printf("^^^ remote_error: err=%hu len=%hu\n", 
      ntohs(sre->sre_error), ntohs(sre->sre_length)); 
     break; 
    case SCTP_SHUTDOWN_EVENT: 
     printf("^^^ shutdown event\n"); 
     break; 
    default: 
     printf("unknown type: %hu\n", snp->sn_header.sn_type); 
     break; 
    } 
} 

/* 
* Receive a message from the network. 
*/ 
static void* getmsg(int fd, struct msghdr *msg, void *buf, size_t *buflen, 
    ssize_t *nrp, size_t cmsglen) 
{ 
    ssize_t nr = 0; 
    struct iovec iov[1]; 

    *nrp = 0; 
    iov->iov_base = buf; 
    msg->msg_iov = iov; 
    msg->msg_iovlen = 1; 

    /* Loop until a whole message is received. */ 
    for (;;) { 
     msg->msg_flags = MSG_XPG4_2; 
     msg->msg_iov->iov_len = *buflen; 
     msg->msg_controllen = cmsglen; 

     nr += recvmsg(fd, msg, 0); 
     if (nr <= 0) { 
      /* EOF or error */ 
      *nrp = nr; 
      return (NULL); 
     } 

     /* Whole message is received, return it. */ 
     if (msg->msg_flags & MSG_EOR) { 
      *nrp = nr; 
      return (buf); 
     } 

     /* Maybe we need a bigger buffer, do realloc(). */ 
     if (*buflen == nr) { 
      buf = realloc(buf, *buflen * 2); 
      if (buf == 0) { 
       fprintf(stderr, "out of memory\n"); 
       exit(1); 
      } 
      *buflen *= 2; 
     } 

     /* Set the next read offset */ 
     iov->iov_base = (char *)buf + nr; 
     iov->iov_len = *buflen - nr; 

    } 
} 

/* 
* The echo server. 
*/ 
static void echo(int fd) 
{ 
    ssize_t nr; 
    struct sctp_sndrcvinfo *sri; 
    struct msghdr msg[1]; 
    struct cmsghdr *cmsg; 
    char cbuf[sizeof (*cmsg) + sizeof (*sri)]; 
    char *buf; 
    size_t buflen; 
    struct iovec iov[1]; 
    size_t cmsglen = sizeof (*cmsg) + sizeof (*sri); 

    /* Allocate the initial data buffer */ 
    buflen = BUFLEN; 
    if ((buf = (char*)malloc(BUFLEN)) == NULL) { 
     fprintf(stderr, "out of memory\n"); 
     exit(1); 
    } 

    /* Set up the msghdr structure for receiving */ 
    memset(msg, 0, sizeof (*msg)); 
    msg->msg_control = cbuf; 
    msg->msg_controllen = cmsglen; 
    msg->msg_flags = 0; 
    cmsg = (struct cmsghdr *)cbuf; 
    sri = (struct sctp_sndrcvinfo *)(cmsg + 1); 

    /* Wait for something to echo */ 
    while ((buf =(char*)getmsg(fd, msg, buf, &buflen, &nr, cmsglen)) != NULL) { 

     /* Intercept notifications here */ 
     if (msg->msg_flags & MSG_NOTIFICATION) { 
      handle_event(buf); 
      continue; 
     } 

     iov->iov_base = buf; 
     msg->msg_iov = iov; 
     msg->msg_iovlen = 1; 
     iov->iov_len = nr; 
     msg->msg_control = cbuf; 
     msg->msg_controllen = sizeof (*cmsg) + sizeof (*sri); 


     write(0, buf, nr); 

     /* Echo it back */ 
     msg->msg_flags = MSG_XPG4_2; 
     if (sendmsg(fd, msg, 0) < 0) { 
      perror("sendmsg"); 
      exit(1); 
     } 
    } 

    if (nr < 0) { 
     perror("recvmsg"); 
    } 
    close(fd); 
} 

int 
main(void) 
{ 
    int lfd; 
    int cfd; 
    int onoff = 1; 
    struct sockaddr_in sin; 
    struct sctp_event_subscribe events; 
    struct sctp_initmsg initmsg; 

    if ((lfd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) == -1) { 
     perror("socket"); 
     exit(1); 
    } 

    sin.sin_family = AF_INET; 
    sin.sin_port = htons(5000); 
    sin.sin_addr.s_addr = INADDR_ANY; 


    if((sctp_bindx(lfd,(struct sockaddr*)&sin,1,SCTP_BINDX_ADD_ADDR))<0){ 
      close(lfd); 
       perror("bind"); 
       exit(1); 

    }  




    if (listen(lfd, 1) == -1) { 
     perror("listen"); 
     exit(1); 
    }else{ 

     printf("Server listening on port 5000....."); 

    } 




    /* Events to be notified for */ 
    (void) memset(&events, 0, sizeof (events)); 
    events.sctp_data_io_event = 1; 
    events.sctp_association_event = 1; 
    events.sctp_send_failure_event = 1; 
    events.sctp_address_event = 1; 
    events.sctp_peer_error_event = 1; 
    events.sctp_shutdown_event = 1; 

    /* Wait for new associations */ 
    for (;;) { 
     if ((cfd = accept(lfd, NULL, 0)) == -1) { 
      perror("accept"); 
      exit(1); 
     } 

     /* Enable ancillary data */ 
     if (setsockopt(cfd, IPPROTO_SCTP, SCTP_EVENTS, &events, 
       sizeof (events)) < 0) { 
      perror("setsockopt SCTP_EVENTS"); 
      exit(1); 
     } 
     /* Echo back any and all data */ 
     echo(cfd); 
    } 
} 

雖然代碼編譯,編譯器會發出警告有關字節順序功能消息( htons,ntohs,ntonl):

-*- mode: compilation; default-directory: "/usr/lib/gcc/x86_64-linux-gnu/4.7.3/include/" -*- 
Compilation started at Wed Jan 15 09:48:12 

gcc sctp_es.c 
sctp_es.c: In function ‘handle_event’: 
sctp_es.c:63:13: warning: ‘force’ attribute directive ignored [-Wattributes] 
sctp_es.c:63:13: warning: ‘force’ attribute directive ignored [-Wattributes] 
sctp_es.c:63:13: warning: ‘force’ attribute directive ignored [-Wattributes] 
sctp_es.c:63:13: warning: ‘force’ attribute directive ignored [-Wattributes] 
sctp_es.c:63:13: warning: ‘force’ attribute directive ignored [-Wattributes] 
sctp_es.c:63:13: warning: ‘force’ attribute directive ignored [-Wattributes] 
sctp_es.c:63:13: warning: ‘force’ attribute directive ignored [-Wattributes] 
sctp_es.c:63:13: warning: ‘force’ attribute directive ignored [-Wattributes] 
sctp_es.c: In function ‘main’: 
sctp_es.c:203:5: warning: ‘force’ attribute directive ignored [-Wattributes] 

Compilation finished at Wed Jan 15 09:48:12 

那麼這裏似乎有什麼麻煩?我用這4個函數創建了一個額外的頭文件,並將其作爲頭添加到頭文件中,但這並不能解決問題。

+0

''從哪裏來? – alk

回答

0

你可能想

#include <arpa/inet.h> 

有原型

uint32_t htonl(uint32_t hostlong); 
uint16_t htons(uint16_t hostshort); 
uint32_t ntohl(uint32_t netlong); 
uint16_t ntohs(uint16_t netshort); 

可用。


也不要

#include <linux/signal.h> 

#include <signal.h> 
+0

可能我加了alk:當我編譯一個使用TCP而不是SCTP的echo服務器程序時,它不會產生這些錯誤。所以,我懷疑sctp頭文件有什麼問題。 –

1

通過添加的字節順序功能實現到頁眉我解決了這個問題現在。在頭文件中還有一些其他的錯誤,並修復了它在沒有任何警告的情況下編譯的錯誤。