1 /** 2 * @brief - Send a message, using advanced SCTP features 3 * The sctp_sendmsg() function allows you to send extra information to a remote application. 4 * Using advanced SCTP features, you can send a message through a specified stream, 5 * pass extra opaque information to a remote application, or define a timeout for the particular message. 6 * 7 * @header - #include <netinet/sctp.h> 8 * 9 * @return ssize_t - The number of bytes sent, or -1 if an error occurs (errno is set). 10 * 11 * @ERRORS 12 * EBADF 13 * An invalid descriptor was specified. 14 * EDESTADDRREQ 15 * A destination address is required. 16 * EFAULT 17 * An invalid user space address was specified for a parameter. 18 * EMSGSIZE 19 * The socket requires that the message be sent atomically, but the size of the message made this impossible. 20 * ENOBUFS 21 * The system couldn't allocate an internal buffer. The operation may succeed when buffers become available. 22 * ENOTSOCK 23 * The argument s isn't a socket. 24 * EWOULDBLOCK 25 * The socket is marked nonblocking and the requested operation would block. 26 */ 27 ssize_t sctp_sendmsg(int s, /*! Socket descriptor. */ 28 const void *msg, /*! Message to be sent. */ 29 size_t len, /*! Length of the message. */ 30 struct sockaddr *to, /*! Destination address of the message. */ 31 socklen_t tolen, /*! Length of the destination address. */ 32 uint32_t ppid, /*! An opaque unsigned value that is passed to the remote end in each user message. 33 The byte order issues are not accounted for and this information is passed opaquely 34 by the SCTP stack from one end to the other. */ 35 uint32_t flags, /*! Flags composed of bitwise OR of these values: 36 MSG_UNORDERED 37 This flag requests the unordered delivery of the message. 38 If the flag is clear, the datagram is considered an ordered send. 39 MSG_ADDR_OVER 40 This flag, in one-to-many style, requests the SCTP stack to override the primary destination address. 41 MSG_ABORT 42 This flag causes the specified association to abort -- by sending 43 an ABORT message to the peer (one-to-many style only). 44 MSG_EOF 45 This flag invokes the SCTP graceful shutdown procedures on the specified association. 46 Graceful shutdown assures that all data enqueued by both endpoints is successfully 47 transmitted before closing the association (one-to-many style only). */ 48 uint16_t stream_no, /*! Message stream number -- for the application to send a message. 49 If a sender specifies an invalid stream number, an error indication is returned and the call fails. */ 50 uint32_t timetolive, /*! Message time to live in milliseconds. 51 The sending side expires the message within the specified time period 52 if the message has not been sent to the peer within this time period. 53 This value overrides any default value set using socket option. 54 If you use a value of 0, it indicates that no timeout should occur on this message. */ 55 uint32_t context); /*! An opaque 32-bit context datum. 56 This value is passed back to the upper layer if an error occurs while sending a message, 57 and is retrieved with each undelivered message. */ 58 59 #include <stdio.h> 60 #include <stdlib.h> 61 #include <string.h> 62 #include <unistd.h> 63 #include <time.h> 64 #include <sys/socket.h> 65 #include <sys/types.h> 66 #include <netinet/in.h> 67 #include <netinet/sctp.h> 68 //#include "common.h" 69 #define MAX_BUFFER 1024 70 #define MY_PORT_NUM 19000 71 #define LOCALTIME_STREAM 0 72 #define GMT_STREAM 1 73 74 int main() 75 { 76 int listenSock, connSock, ret; 77 struct sockaddr_in servaddr; 78 char buffer[MAX_BUFFER + 1]; 79 time_t currentTime; 80 81 /* Create SCTP TCP-Style. Socket */ 82 listenSock = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP ); // 注意这里的IPPROTO_SCTP 83 /* Accept connections from any interface */ 84 bzero( (void *)&servaddr, sizeof(servaddr) ); 85 servaddr.sin_family = AF_INET; 86 servaddr.sin_addr.s_addr = htonl( INADDR_ANY ); 87 servaddr.sin_port = htons(MY_PORT_NUM); 88 /* Bind to the wildcard address (all) and MY_PORT_NUM */ 89 ret = bind( listenSock, 90 (struct sockaddr *)&servaddr, sizeof(servaddr) ); 91 /* Place the server socket into the listening state */ 92 listen( listenSock, 5 ); 93 /* Server loop... */ 94 while( 1 ) 95 { 96 /* Await a new client connection */ 97 connSock = accept( listenSock, 98 (struct sockaddr *)NULL, (int *)NULL ); 99 /* New client socket has connected */ 100 /* Grab the current time */ 101 currentTime = time(NULL); 102 /* Send local time on stream 0 (local time stream) */ 103 snprintf( buffer, MAX_BUFFER, "%s ", ctime(currentTime) ); 104 ret = sctp_sendmsg( connSock, 105 (void *)buffer, (size_t)strlen(buffer), 106 NULL, 0, 0, 0, LOCALTIME_STREAM, 0, 0 ); 107 /* Send GMT on stream 1 (GMT stream) */ 108 snprintf( buffer, MAX_BUFFER, "%s ", 109 asctime( gmtime( currentTime ) ) ); 110 ret = sctp_sendmsg( connSock, 111 (void *)buffer, (size_t)strlen(buffer), 112 NULL, 0, 0, 0, GMT_STREAM, 0, 0 ); 113 /* Close the client connection */ 114 close( connSock ); 115 } 116 return 0; 117 } 118 119 120 #include <stdio.h> 121 #include <stdlib.h> 122 #include <string.h> 123 #include <unistd.h> 124 #include <sys/socket.h> 125 #include <sys/types.h> 126 #include <netinet/in.h> 127 #include <netinet/sctp.h> 128 #include <arpa/inet.h> 129 //#include "common.h" 130 #define MAX_BUFFER 1024 131 #define MY_PORT_NUM 19000 132 #define LOCALTIME_STREAM 0 133 #define GMT_STREAM 1 134 135 int main() 136 { 137 int connSock, in, i, flags; 138 struct sockaddr_in servaddr; 139 struct sctp_sndrcvinfo sndrcvinfo; 140 struct sctp_event_subscribe events; 141 char buffer[MAX_BUFFER + 1]; 142 /* Create an SCTP TCP-Style. Socket */ 143 connSock = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP ); 144 /* Specify the peer endpoint to which we'll connect */ 145 bzero( (void *)&servaddr, sizeof(servaddr) ); 146 servaddr.sin_family = AF_INET; 147 servaddr.sin_port = htons(MY_PORT_NUM); 148 servaddr.sin_addr.s_addr = inet_addr( "127.0.0.1" ); 149 /* Connect to the server */ 150 connect( connSock, (struct sockaddr *)&servaddr, sizeof(servaddr) ); 151 /* Enable receipt of SCTP Snd/Rcv Data via sctp_recvmsg */ 152 memset( (void *)&events, 0, sizeof(events) ); 153 events.sctp_data_io_event = 1; 154 setsockopt( connSock, SOL_SCTP, SCTP_EVENTS, 155 (const void *)&events, sizeof(events) ); 156 /* Expect two messages from the peer */ 157 for (i = 0 ; i < 2 ; i++) 158 { 159 in = sctp_recvmsg( connSock, (void *)buffer, sizeof(buffer), 160 (struct sockaddr *)NULL, 0, 161 &sndrcvinfo, &flags ); 162 /* Null terminate the incoming string */ 163 buffer[in] = 0; 164 if (sndrcvinfo.sinfo_stream == LOCALTIME_STREAM) 165 { 166 printf("(Local) %s ", buffer); 167 } 168 else if (sndrcvinfo.sinfo_stream == GMT_STREAM) 169 { 170 printf("(GMT ) %s ", buffer); 171 } 172 } 173 /* Close our socket and exit */ 174 close(connSock); 175 return 0; 176 }