int main(int argc,char **argv) { int sock_fd; int msg_flags; // 記錄要傳送訊息時的相關設定,包括association... char readbuf[BUFFERSIZE]; struct sockaddr_in cliaddr, servaddr; struct sctp_sndrcvinfo sri; struct sctp_event_subscribe evnts; socklen_t len; size_t rd_sz; // size_t指的就是unsigned long int ret_value=0; struct sockaddr *laddrs; // 用來記錄local addresses struct sockaddr *paddrs; union sctp_notification *snp; // 用來轉換傳送過來的訊息 struct sctp_shutdown_event *sse; // 當傳送過來的是shutdown event,則可以用這一個指標指到傳送過來的資料 struct sctp_assoc_change *sac; struct sctp_paddr_change *spc; struct sctp_remote_error *sre; struct sctp_send_failed *ssf; #ifdef UN_MOD struct sctp_adaptation_event *ae; #else struct sctp_adaption_event *ae; #endif struct sctp_pdapi_event *pdapi; int close_time = 30; const char *str; if (argc < 2) { printf("Error, use %s [list of addresses to bind]\n",argv[0]); exit(-1); } // 建立socket的型態為SCTP的one-to-many的型態 sock_fd = Socket(AF_INET,SOCK_SEQPACKET, IPPROTO_SCTP); if (sock_fd == -1) { printf("socket error\n"); exit(-1); } // 初始化要bind的server資料,連續加入多個要綁的ip address int i; for (i=1;i<argc;i++) { memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family = AF_INET; inet_pton(AF_INET,argv[i],&servaddr.sin_addr); // 把socket與此ip綁在一起 servaddr.sin_port = htons(SERV_PORT); // 把這一個ip與socket綁在一起 if ((ret_value=sctp_bindx(sock_fd,(struct sockaddr*) &servaddr,1,SCTP_BINDX_ADD_ADDR))==-1) { printf("Can't bind the address %s\n",argv[i]); exit(-1); } else { // 無論如何一定會bind成功,因為,若給錯的ip,則會bind此host端的所有ip printf("Bind %s success!!\n",argv[i]); } } // 設定事件 bzero(&evnts,sizeof(evnts)); evnts.sctp_data_io_event=1; // Enable sctp_sndrcvinfo to come with each recvmsg,否則就接收不到對方的資訊了 evnts.sctp_shutdown_event=1; // 喔耶!當client端shutdown時,會通知server evnts.sctp_association_event=1; // 監測 evnts.sctp_address_event = 1; evnts.sctp_send_failure_event = 1; evnts.sctp_peer_error_event = 1; evnts.sctp_partial_delivery_event = 1; #ifdef UN_MOD evnts.sctp_adaptation_layer_event = 1; #else evnts.sctp_adaption_layer_event = 1; #endif ret_value = setsockopt(sock_fd,IPPROTO_SCTP,SCTP_EVENTS,&evnts,sizeof(evnts)); if (ret_value == -1) { printf("setsockopt error\n"); exit(-1); } ret_value = setsockopt(sock_fd,IPPROTO_SCTP,SCTP_AUTOCLOSE,&close_time,sizeof(close_time)); if (ret_value == -1) { printf("setsockopt error\n"); exit(-1); } // 設定多少個client可以連線 ret_value = listen(sock_fd,LISTENQ); if (ret_value == -1) { printf("listen error\n"); exit(-1); } printf("start wait...\n"); for (;;) { memset(readbuf,0,sizeof(readbuf)); len = sizeof(struct sockaddr_in); rd_sz = sctp_recvmsg(sock_fd,readbuf,sizeof(readbuf),(struct sockaddr *) &cliaddr,&len,&sri,&msg_flags); //======================================================================== // test the sctp_getladdrs function - start ret_value = sctp_getladdrs(sock_fd,sri.sinfo_assoc_id,&laddrs); printf("The sctp_getladdrs return value is %d\n",ret_value); // test the sctp_getladdrs function - end // test the sctp_getpaddrs function - start ret_value = sctp_getpaddrs(sock_fd,sri.sinfo_assoc_id,&paddrs); printf("The sctp_getpaddrs return value is %d\n",ret_value); // test the sctp_getpaddrs function - end //======================================================================== if (msg_flags & MSG_NOTIFICATION) { // 表示收到一個事件通告,而非一個資料 snp = (union sctp_notification *) readbuf; switch (snp->sn_header.sn_type) { case SCTP_SHUTDOWN_EVENT: sse = &snp->sn_shutdown_event; printf("SCTP_SHUTDOWN_EVENT: assoc=0x%x\n",(uint32_t) sse->sse_assoc_id); break; case SCTP_ASSOC_CHANGE: sac = &snp->sn_assoc_change; switch (sac->sac_state) { case SCTP_COMM_UP: printf("COMMUNICATION UP\n"); break; case SCTP_COMM_LOST: printf("COMMUNICATION LOST\n"); break; case SCTP_RESTART: printf("RESTART\n"); break; case SCTP_SHUTDOWN_COMP: printf("SHUTDOWN COMPLETE\n"); break; case SCTP_CANT_STR_ASSOC: printf("CAN'T START ASSOC\n"); break; default: printf("UNKNOW\n"); break; } break; case SCTP_PEER_ADDR_CHANGE: spc = &snp->sn_paddr_change; switch(spc->spc_state) { case SCTP_ADDR_AVAILABLE: str = "ADDRESS AVAILABLE"; break; case SCTP_ADDR_UNREACHABLE: str = "ADDRESS UNREACHABLE"; break; case SCTP_ADDR_REMOVED: str = "ADDRESS REMOVED"; break; case SCTP_ADDR_ADDED: str = "ADDRESS ADDED"; break; case SCTP_ADDR_MADE_PRIM: str = "ADDRESS MADE PRIMARY"; break; case SCTP_ADDR_CONFIRMED: str = "ADDRESS MADE CONFIRMED"; break; default: str = "UNKNOW"; break; } printf("SCTP_PEER_ADDR_CHANGE: %s\n",str); break; case SCTP_REMOTE_ERROR: sre = &snp->sn_remote_error; printf("SCTP_REMOTE_ERROR\n"); break; case SCTP_SEND_FAILED: ssf = &snp->sn_send_failed; printf("SCTP_SEND_FAILED\n"); break; #ifdef UN_MOD case SCTP_ADAPTATION_INDICATION: ae = &snp->sn_adaptation_event; printf("SCTP_ADAPTION_INDICATION\n"); break; #else case SCTP_ADAPTION_INDICATION: ae = &snp->sn_adaption_event; printf("SCTP_ADAPTION_INDICATION\n"); break; #endif case SCTP_PARTIAL_DELIVERY_EVENT: pdapi = &snp->sn_pdapi_event; if (pdapi->pdapi_indication == SCTP_PARTIAL_DELIVERY_ABORTED) printf("SCTP_PARTIAL_DELIEVERY_ABORTED\n"); else printf("Unknown SCTP_PARTIAL_DELIVERY_EVENT\n"); break; default: printf("UNKNOWN notification\n"); break; } continue; } printf("%s",readbuf); ret_value = sctp_sendmsg(sock_fd,readbuf,rd_sz,(struct sockaddr *) &cliaddr,len,sri.sinfo_ppid,sri.sinfo_flags,sri.sinfo_stream,0,0); if (ret_value == -1) { printf("sctp_sendmsg error\n"); exit(-1); } } return 0; }
void message::printsys() { len = sizeof(struct sockaddr_in); rd_sz = sctp_recvmsg(sock_fd,readbuf,sizeof(readbuf),(struct sockaddr *) &cliaddr,&len,&sri,&msg_flags); ret_value = sctp_sendmsg(sock_fd,readbuf,rd_sz,(struct sockaddr *) &cliaddr,len,sri.sinfo_ppid,sri.sinfo_flags,sri.sinfo_stream,0,0); if (ret_value == -1) { qWarning("sctp_sendmsg error"); exit(-1); } }
int Sctp_sendmsg(int s, void* data, size_t len, struct sockaddr* to, socklen_t tolen, uint32_t ppid, uint32_t flags, uint16_t stream_no, uint32_t timetolive, uint32_t context) { int ret; ret = sctp_sendmsg(s, data, len, to, tolen, ppid, flags, stream_no, timetolive, context); if (ret < 0) { err_sys("sctp_sendmsg error"); } return (ret); }
int main(int argc, char **argv) { int sock_fd,msg_flags; char readbuf[BUFFSIZE]; struct sockaddr_in6 servaddr, cliaddr; struct sctp_sndrcvinfo sri; struct sctp_event_subscribe evnts; int stream_increment=1; socklen_t len; size_t rd_sz; if (argc == 2) stream_increment = atoi(argv[1]); sock_fd = socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP); if (sock_fd < 0) { perror("socket()"); exit(errno); } bzero(&servaddr, sizeof(servaddr)); servaddr.sin6_family = AF_INET; // servaddr.sin6_addr.s_addr = htonl(INADDR_ANY); servaddr.sin6_port = htons(SERV_PORT); bind(sock_fd, (SA *) &servaddr, sizeof(servaddr)); bzero(&evnts, sizeof(evnts)); evnts.sctp_data_io_event = 1; setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts)); listen(sock_fd, LISTENQ); for ( ; ; ) { len = sizeof(struct sockaddr_in6); rd_sz = sctp_recvmsg(sock_fd, readbuf, sizeof(readbuf), (SA *)&cliaddr, &len, &sri,&msg_flags); if(stream_increment) { sri.sinfo_stream++; if(sri.sinfo_stream >= sctp_get_no_strms(sock_fd,(SA *)&cliaddr, len)) sri.sinfo_stream = 0; } sctp_sendmsg(sock_fd, readbuf, rd_sz, (SA *)&cliaddr, len, sri.sinfo_ppid, sri.sinfo_flags, sri.sinfo_stream, 0, 0); } }
static void echo(int fd, int socketModeUDP) { struct sctp_sndrcvinfo sri; char buf[BUFLEN]; size_t buflen; ssize_t received; int flags; unsigned int outgoing = 1; union sctp_notification *snp; /* Wait for something to echo */ buflen = sizeof(buf); flags = 0; received = sctp_recvmsg(fd, buf, buflen, NULL, 0, &sri, &flags); while(received > 0) { /* Intercept notifications here */ if(flags & MSG_NOTIFICATION) { snp = (union sctp_notification *)buf; if(snp->sn_header.sn_type == SCTP_ASSOC_CHANGE) { /* incoming = snp->sn_assoc_change.sac_inbound_streams; */ outgoing = snp->sn_assoc_change.sac_outbound_streams; } handle_event(buf); } else { printf("got %u bytes on stream %hu:\n", (unsigned int)received, sri.sinfo_stream); fflush(stdout); write(0, buf, received); /* Echo it back */ if(sctp_sendmsg(fd, buf, received, NULL, 0, 0x29091976, 0, sri.sinfo_stream % outgoing, 0, 0) < 0) { perror("sendmsg"); exit(1); } } buflen = sizeof(buf); flags = 0; received = sctp_recvmsg(fd, buf, buflen, NULL, 0, &sri, &flags); } if(received < 0) { perror("sctp_recvmsg"); } if(socketModeUDP == 0) { ext_close(fd); } }
static PyObject* sctp_send_msg(PyObject* dummy, PyObject* args) { int fd, msg_len, size_sent, ppid, flags, stream, ttl, context; const char *msg; char *to; int port; struct sockaddr_storage sto; struct sockaddr_storage *psto = &sto; int sto_len; PyObject *ret = 0; if (! PyArg_ParseTuple(args, "is#(si)iiiii", &fd, &msg, &msg_len, &to, &port, &ppid, &flags, &stream, &ttl, &context)) { return ret; } if (msg_len <= 0 && (! (flags & MSG_EOF))) { PyErr_SetString(PyExc_ValueError, "Empty messages are not allowed, except if coupled with the MSG_EOF flag."); return ret; } // TODO: "to" can contain and assoc_id. For this to be possible, we will need to // use bare sendmsg() instead of sctp_sendmsg(). if (strlen(to) == 0) { // special case: should pass NULL sto_len = 0; psto = 0; } else { if (! to_sockaddr(to, port, (struct sockaddr*) psto, &sto_len)) { PyErr_SetString(PyExc_ValueError, "Invalid Address"); return ret; } } size_sent = sctp_sendmsg(fd, msg, msg_len, (struct sockaddr*) psto, sto_len, ppid, flags, stream, ttl, context); if (size_sent < 0) { PyErr_SetFromErrno(PyExc_IOError); return ret; } ret = PyInt_FromLong(size_sent); return ret; }
/*************************************************************************** ** Used by M3UA to send messages on the specified assoc/stream combination. ****************************************************************************/ m3_s32 m3ua_sendmsg(m3_u32 assoc_id, m3_u32 stream_id, m3_u32 msglen, m3_u8 *pmsg) { iu_log_debug("%s %d: %s\n",__FILE__, __LINE__, __func__); int ret; int tid = assoc_table[assoc_id].to; //msc 0 sgsn 1 int fid = assoc_table[assoc_id].from;//msc 0 , sgsn 1 iu_log_debug("assoc_id = %d, from = %d, to = %d\n",assoc_id, assoc_table[assoc_id].from, assoc_table[assoc_id].to); struct sockaddr_in* paddr = NULL; if(0 == to[tid].issecondary) { paddr = (struct sockaddr_in*)&to[tid].addr[0]; } else { paddr = (struct sockaddr_in*)&to[tid].addr[1]; } int sock_fd = from[fid].sockid; iu_log_debug("sock_fd = %d\n", sock_fd); unsigned int ppid = 3; #ifdef __M3UA_PRINT_OUTGOING_MESSAGE__ int m_idx, byte; iu_log_debug("\n<------ Outgoing Message ------>\n"); iu_log_debug("\n Number of Bytes in Message = %d\n", msglen); for (m_idx = 0; m_idx < msglen; ) { byte = pmsg[m_idx++]; iu_log_debug("%02x ", byte); if (0 == m_idx%4) { iu_log_debug("\n"); } } #endif iu_log_debug("msglen = %d, stream_id = %d\n",msglen,stream_id); ppid = htonl(ppid); iu_log_debug("assoc_id = %d, tid = %d, fid = %d, addr = %s, port = %d &&&&&&&&\n", assoc_id, tid, fid, inet_ntoa(paddr->sin_addr), paddr->sin_port); ret = sctp_sendmsg (sock_fd, pmsg, msglen, (struct sockaddr *)paddr, sizeof(struct sockaddr), ppid, 0, stream_id, 0, 0); if (0 >= ret) { iu_log_debug("ERRNO:%d\n", errno); perror("E_sctp_sendmsg_Fail"); } return 0; }
void zmq::sctp_engine_t::out_event (handle_t handle_) { message_t msg; if (!mux.read (&msg)) { // If there are no messages to send, stop polling for output. poller->reset_pollout (handle); return; } // Send the data over the wire. ssize_t nbytes = sctp_sendmsg (s, msg.data (), msg.size (), NULL, 0, 0, 0, 0, 0, 0); errno_assert (nbytes != -1); assert (nbytes == (ssize_t) msg.size ()); }
int main(int argc,char **argv) { int sock_fd,msg_flags; char readbuf[1024]; struct sockaddr_in servaddr,cliaddr; struct sctp_sndrcvinfo sri; struct sctp_event_subscribe evnts; socklen_t len; size_t rd_sz; if ((sock_fd = socket(AF_INET,SOCK_SEQPACKET,IPPROTO_SCTP)) < 0) { perror("socket"); } bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(9877); if (bind(sock_fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { perror("bind"); } bzero(&evnts, sizeof(evnts)); evnts.sctp_data_io_event = 1; if (setsockopt(sock_fd,IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts)) < 0) { perror("setsockopt"); } if (listen(sock_fd,5) < 0) { perror("listen"); } for (;;) { len = sizeof(struct sockaddr_in); printf("start wait...\n"); rd_sz = sctp_recvmsg(sock_fd,readbuf, sizeof(readbuf), (struct sockaddr *)&cliaddr, &len, &sri, &msg_flags); printf("sctp_recvmsg() received %d bytes from %s:%d.\n", (int)rd_sz, inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port)); if (rd_sz > 0) { if (sctp_sendmsg(sock_fd, readbuf, rd_sz, (struct sockaddr *)&cliaddr, len, sri.sinfo_ppid, sri.sinfo_flags, sri.sinfo_stream, 0, 0) < 0) { perror("sctp_sendmsg"); } } } return 0; }
/** * @brief Send data using SEQPKT socket. * * The data is sent and PPID and Stream ID are set as requested. * * @param sock The socket to use when sending. * @param ppid PPID for the SCTP chunk * @param streamno The stream no for the stream where the data is to be written. * @param dst Destination host * @param dst_len Length of the sockaddr structure. * @param chunk The data to send. * @param chunk_size Number of bytes to send. * * @return Number of bytes sent on success <0 on error. */ int sendit( int sock, uint32_t ppid, uint16_t streamno, struct sockaddr *dst, size_t dst_len, uint8_t *chunk, int chunk_size ) { int ret; TRACE("Sending with ppid %d and stream no %d\n", ppid, streamno); ret = sctp_sendmsg( sock, chunk, chunk_size, dst, dst_len, ppid, /* ppid */ 0, /* flags */ streamno, /* stream no */ 0, /* ttl */ 0xF00F /* context */ ); TRACE( "Sent %d / %d bytes \n", ret, chunk_size ); return ret; }
int main() { int connSock, in, i, ret, flags; struct sockaddr_in servaddr; struct sctp_status status; char buffer[MAX_BUFFER+1]; connSock = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP ); if(connSock == -1) die("socket()"); bzero( (void *)&servaddr, sizeof(servaddr) ); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(MY_PORT_NUM); // servaddr.sin_addr.s_addr = inet_addr( "127.0.0.1" ); servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); ret = connect( connSock, (struct sockaddr *)&servaddr, sizeof(servaddr) ); if(ret == -1) die("connect()"); printf("Enter data to send : "); gets(buffer); // scanf("%s", buffer); //getchar(); ret = sctp_sendmsg( connSock, (void *)buffer, (size_t)strlen(buffer), NULL, 0, 0, 0, 0, 0, 0 ); memset(buffer, '\0', sizeof(buffer)); // printf("ret = %d\n", ret); in = sctp_recvmsg( connSock, (void *)buffer, sizeof(buffer), (struct sockaddr *)NULL, 0, 0, 0 ); // printf("in = %d\n", in); printf("response = %s\n", buffer); memset(buffer, '\0', sizeof(buffer)); close(connSock); return 0; }
static gssize sctp_socket_send_with_blocking (GSocket * socket, guint streamid, guint32 timetolive, const gchar * buffer, gsize size, gboolean blocking, GCancellable * cancellable, GError ** error) { gssize ret; if (g_socket_is_closed (socket)) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED, "Socket is already closed"); return -1; } if (g_cancellable_set_error_if_cancelled (cancellable, error)) return -1; while (TRUE) { if (blocking && !g_socket_condition_wait (socket, G_IO_OUT, cancellable, error)) return -1; if ((ret = sctp_sendmsg (g_socket_get_fd (socket), buffer, size, NULL, 0, 0, 0, streamid, timetolive, 0)) < 0) { if (errno == EINTR) continue; if (blocking) { if (errno == EWOULDBLOCK || errno == EAGAIN) continue; } g_set_error (error, G_IO_ERROR, errno, "Error sending data: %s", strerror (errno)); return -1; } break; } return ret; }
static int sctp_send_msg(int32_t sctp_assoc_id, uint16_t stream, const uint8_t *buffer, const uint32_t length) { struct sctp_association_s *assoc_desc = NULL; DevAssert(buffer != NULL); if ((assoc_desc = sctp_is_assoc_in_list(sctp_assoc_id)) == NULL) { SCTP_DEBUG("This assoc id has not been fount in list (%d)\n", sctp_assoc_id); return -1; } if (assoc_desc->sd == -1) { /* The socket is invalid may be closed. */ return -1; } SCTP_DEBUG("[%d][%d] Sending buffer %p of %d bytes on stream %d with ppid %d\n", assoc_desc->sd, sctp_assoc_id, buffer, length, stream, assoc_desc->ppid); /* Send message_p on specified stream of the sd association */ if (sctp_sendmsg(assoc_desc->sd, (const void *)buffer, length, NULL, 0, assoc_desc->ppid, 0, stream, 0, 0) < 0) { SCTP_ERROR("send: %s:%d", strerror(errno), errno); return -1; } assoc_desc->messages_sent++; SCTP_DEBUG("Successfully sent %d bytes on stream %d\n", length, stream); return 0; }
int send_bframe() { int ret; buffer[0] = 'B'; if ((ret = sctp_sendmsg(fd, (const void *)buffer, SIZE_OF_P_FRAME, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), htonl(66), /* PPID */ 0, /* flags */ 1, /* stream identifier */ 0, /* Max number of rtx */ 0 /* context */ )) < 0) { perror("sctp_sendmsg - B"); } else { bcount++; } printf("I:%d P:%d B:%d\r", icount, pcount, bcount); fflush(stdout); return(ret); }
void sctpstr_cli_echoall(FILE *fp,int sock_fd,struct sockaddr *to,socklen_t tolen) { struct sockaddr_in peeraddr; struct sctp_sndrcvinfo sri; char sendline[SCTP_MAXLINE], recvline[SCTP_MAXLINE]; socklen_t len; int rd_sz,i,strsz; int msg_flags; int ret_value=0; // the client initializes the sri structure used to set up the stream it will be sending and receiving from bzero(sendline,sizeof(sendline)); bzero(&sri,sizeof(sri)); while(fgets(sendline,SCTP_MAXLINE-9,fp) != NULL) { strsz = strlen(sendline); // delete the newline character that is at the end of the buffer if (sendline[strsz-1] == '\n') { sendline[strsz-1]='\0'; strsz--; } // 傳送SERV_MAX_SCTP_STRM筆資料給server for (i=0; i<SERV_MAX_SCTP_STRM; i++) { snprintf(sendline+strsz,sizeof(sendline)-strsz,".msg.%d",i); ret_value = sctp_sendmsg(sock_fd,sendline,sizeof(sendline),to,tolen,0,0,i,0,0); if (ret_value == -1) { printf("sctp_sendmsg error\n"); exit(-1); } } // 由server接收SERV_MAX_SCTP_STRM筆資料 for (i=0; i<SERV_MAX_SCTP_STRM; i++) { len = sizeof(peeraddr); rd_sz = sctp_recvmsg(sock_fd,recvline,sizeof(recvline),(struct sockaddr *) &peeraddr,&len,&sri,&msg_flags); printf("From str:%d seq:%d (assoc:0x%x):",sri.sinfo_stream,sri.sinfo_ssn,(u_int) sri.sinfo_assoc_id); printf("%.*s\n",rd_sz,recvline); } } }
int send_to_target(int s, const void *msg, size_t len, struct sockaddr *to, socklen_t tolen, uint32_t ppid, uint32_t flags, uint16_t stream_no, uint32_t timetolive, uint32_t context) { int status = -1; do { int error = sctp_sendmsg(s, msg, len, to, tolen, ppid, flags, stream_no, timetolive, context); if (len != error) { perror("sctp_sendmsg"); break; } status = 0; } while (0); return status; }
int main(int argc, char** argv) { int sock;//, msg_flags; char readbuf[2000]; struct sockaddr_in servaddr; struct sctp_sndrcvinfo sri; struct sctp_event_subscribe evnts; struct hostent *addr; struct sctp_initmsg initmsg; char inFile[2048];//NULL; FILE* file = NULL; int sz,sent = 0; socklen_t len; size_t rd_sz; if(argc < 3) { printf("Missing argument - use '%s peer file'\n",argv[0]); exit(-1); } strcpy(inFile,argv[2]); bzero(&servaddr,sizeof(servaddr)); if(atoi(argv[1]) > 0) { servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = inet_addr(argv[1]); } else { if ((addr=gethostbyname(argv[1])) == NULL) { //Adress not found perror("bad hostname"); exit(-1); } //Set address family servaddr.sin_family = addr->h_addrtype; //Copy and set adress bcopy(addr->h_addr_list[0],(char*)&servaddr.sin_addr.s_addr, sizeof(struct in_addr)); } if((file = fopen(argv[2],"r")) == NULL) { printf("file not found: %s\n", argv[2]); exit(-1); } servaddr.sin_port = htons(2960); sock = socket(AF_INET,SOCK_SEQPACKET,IPPROTO_SCTP); bzero(&evnts,sizeof(evnts)); evnts.sctp_data_io_event = 1; if(setsockopt(sock,IPPROTO_SCTP,SCTP_EVENTS,&evnts,sizeof(evnts))<0) perror("setsockopt evnts"); bzero(&initmsg,sizeof(initmsg)); initmsg.sinit_num_ostreams = 2; initmsg.sinit_max_instreams = 2; initmsg.sinit_max_attempts = 0; initmsg.sinit_max_init_timeo = 0; len = sizeof(initmsg); if (setsockopt(sock, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg)) < 0) { perror("setsockopt SCTP_INITMSG"); close(sock); exit(-1); } sri.sinfo_stream = 0; printf("SENDING FILENAME: %s\n",inFile); len = sizeof(servaddr); if((sz = sctp_sendmsg(sock,inFile,strlen(inFile),(struct sockaddr*)&servaddr,len,sri.sinfo_ppid,sri.sinfo_flags,sri.sinfo_stream,0,0)) < strlen(argv[2])) { printf("could not send file name\n"); close(sock); exit(-1); } else { printf("filename sent\n"); } sri.sinfo_ppid = 0; while(!feof(file) && !ferror(file)) { sri.sinfo_ppid++; sri.sinfo_ppid = sri.sinfo_ppid % 10; printf("using ppid %d\n", sri.sinfo_ppid); if((rd_sz = fread(readbuf,sizeof(char),512,file))>=0) { if((sz = sctp_sendmsg(sock,readbuf,rd_sz,(struct sockaddr*)&servaddr,len,sri.sinfo_ppid,sri.sinfo_flags,sri.sinfo_stream,0,0))<0) perror("send error\n"); else sent += sz; } else{ perror("file read error\n"); } } if(ferror(file)) { perror("file error\n"); } bzero(readbuf,sizeof(readbuf)); sri.sinfo_flags = MSG_EOF; if(sctp_sendmsg(sock,readbuf,0,(struct sockaddr*)&servaddr,len,sri.sinfo_ppid,sri.sinfo_flags,sri.sinfo_stream,0,0) < 0) perror("sending EOF\n"); printf("%d bytes sent successfully\n",sent); fclose(file); shutdown(sock,SHUT_RDWR); return 0; }
int main(int argc, char **argv) { int i, j; int size, align_size; char *s_buf, *r_buf; double t_start = 0.0, t_end = 0.0, t = 0.0; struct sockaddr_in *dest = malloc(sizeof(struct sockaddr_in)); struct sctp_sndrcvinfo sri; struct sockaddr_in cli; socklen_t s = sizeof(struct sockaddr_in); int msg_flags = 0; int n=-1; char mode[15]; struct timeval start, end; struct dp datapoints[DATAPOINTS]; int num_dp = 0; FILE *file; char filename[PRINTARRAY]; char ascii_size[PRINTARRAY]; int name[] = {CTL_KERN, KERN_OSTYPE}; int namelen = 2; char oldval[15]; size_t len = sizeof(oldval); int error; if (argc < 3) { printf("Usage: %s dst-ip dest-port\n", argv[0]); exit(1); } #if defined(SCTP_USERMODE) uint32_t optval=1; struct socket *psock = NULL; strcpy(mode, "Userspace"); #else //kernel mode int sock_fd; strcpy(mode, "Kernel"); #endif align_size = getpagesize(); assert(align_size <= MAX_ALIGNMENT); s_buf = (char *) (((unsigned long) s_buf1 + (align_size - 1)) / align_size * align_size); r_buf = (char *) (((unsigned long) r_buf1 + (align_size - 1)) / align_size * align_size); error = sysctl (name, namelen, (void *)oldval, &len, NULL /* newval */, 0 /* newlen */); if (error) { printf("sysctl() error\n"); exit(1); } strcpy(filename, "BWbenchmark"); sprintf(ascii_size,"%s%smode",oldval,mode); strcat(filename, ascii_size); strcat(filename,".txt"); #if defined(SCTP_USERMODE) sctp_init(); SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable)=1; if( !(psock = userspace_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) ){ printf("user_socket() returned NULL\n"); exit(1); } #else //Kernel mode if((sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) == -1) { printf("socket error\n"); exit(1); } #endif /* prepare destination adddress */ bzero(dest, sizeof(struct sockaddr_in)); dest->sin_family = AF_INET; dest->sin_addr.s_addr = inet_addr(argv[1]); dest->sin_port = htons((unsigned short) atoi(argv[2])); #if defined(__Userspace_os_FreeBSD) dest->sin_len = sizeof(struct sockaddr); #endif #if defined(SCTP_USERMODE) /* call userspace_connect which eventually calls sctp_send_initiate */ if( userspace_connect(psock, (struct sockaddr *) dest, sizeof(struct sockaddr_in)) == -1 ) { printf("userspace_connect failed. exiting...\n"); exit(1); } sctp_setopt(psock, SCTP_NODELAY, &optval, sizeof(uint32_t), NULL); #else //Kernel mode if((connect(sock_fd, (struct sockaddr *) dest, sizeof(struct sockaddr_in))) == -1) { perror("connect error\n"); exit(1); } /* Setting the send and receive socket buffer sizes */ const int maxbufsize = 65536 * 3; int sndrcvbufsize = maxbufsize; int sndrcvbufsize_len; int rc; sndrcvbufsize_len = sizeof(sndrcvbufsize); rc = setsockopt(sock_fd, SOL_SOCKET, SO_SNDBUF, &sndrcvbufsize, sndrcvbufsize_len); if (rc == -1) { perror("can't set the socket send size to requested one"); exit(1); } rc = setsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, &sndrcvbufsize, sndrcvbufsize_len); if (rc == -1) { perror("can't set the socket receive size to requested one"); exit(1); } /* turning nagle off */ int no_nagle = 1; if (setsockopt(sock_fd, IPPROTO_SCTP, SCTP_NODELAY, (char *) &no_nagle, sizeof(no_nagle)) < 0){ perror("can't setsockopt to no_nagle\n"); exit(1); } #endif num_dp = 0; int retval = 0; printf("\nRunning in %s mode\nStoring results in file %s\n\n", mode, filename); fprintf(stdout, "# %s %s\n", mode, "Mode: Bandwidth Benchmark Similar to OSU"); fprintf(stdout, "%-*s%*s\n", 10, "# Size", FIELD_WIDTH, "Bandwidth (MB/s)"); fflush(stdout); /* Bandwidth test */ for(size = 1; size <= MAX_MSG_SIZE; size *= 2) { /* touch the data */ for(i = 0; i < size; i++) { s_buf[i] = 'a'; r_buf[i] = 'b'; } if(size > large_message_size) { loop = loop_large; skip = skip_large; window_size = window_size_large; } for(i = 0; i < loop + skip; i++) { if(i == skip) { gettimeofday(&start, NULL); t_start = (double) start.tv_sec + .000001 * (double) start.tv_usec; } for(j = 0; j < window_size; j++) { #if defined(SCTP_USERMODE) if((retval = userspace_sctp_sendmsg(psock /* struct socket *so */, s_buf /* const void *data */, size /* size_t len */, (struct sockaddr *)dest /* const struct sockaddr *to */, sizeof(struct sockaddr_in) /* socklen_t tolen */, 0 /* u_int32_t ppid */, 0 /* u_int32_t flags */, 3 /* u_int16_t stream_no */, 0 /* u_int32_t timetolive */, 0 /* u_int32_t context */))<=0) { printf("userspace_sctp_sendmsg returned retval=%d errno=%d\n", retval, errno); exit(1); } #else //Kernel mode if ((retval = sctp_sendmsg(sock_fd, (void *)s_buf, (size_t)size, NULL, 0, 0, 0, 3, 0, 0)) <=0 ) { printf("sctp_sendmsg returned retval=%d errno=%d\n", retval, errno); exit(1); } #endif } #if defined(SCTP_USERMODE) if ((n = userspace_sctp_recvmsg(psock, r_buf, 4, (struct sockaddr *) &cli, &s, &sri, &msg_flags)) <=0 ) { printf(".....userspace_sctp_recvmsg returned n=%d errno=%d\n", n, errno); break; } #else //Kernel mode if ((n = sctp_recvmsg(sock_fd, r_buf, 4, (struct sockaddr *) &cli, &s, &sri, &msg_flags)) <=0 ) { printf("sctp_recvmsg returned n=%d errno=%d\n", n, errno); break; } #endif } gettimeofday(&end, NULL); t_end = (double) end.tv_sec + .000001 * (double) end.tv_usec; t = t_end - t_start; double tmp = size / 1e6 * loop * window_size; fprintf(stdout, "%-*d%*.*f\n", 10, size, FIELD_WIDTH, FLOAT_PRECISION, tmp / t); fflush(stdout); datapoints[num_dp].msg_size = size; datapoints[num_dp].tottime = t; datapoints[num_dp].bw = tmp/t; num_dp++; } printf("Client closing socket...errno=%d\n", errno); free(dest); #if defined(SCTP_USERMODE) userspace_close(psock); #else close(sock_fd); #endif printf("Sleeping for 60 secs\n"); sleep(60); file = fopen(filename, "w+"); if(file == NULL) { perror("could not open results file"); } else { for (j=0; j<num_dp; j++) { fprintf(file,"%d , %.2f , %.2f\n",datapoints[j].msg_size, datapoints[j].tottime, datapoints[j].bw); /*write datapoints to file*/ } fclose(file); } #if defined(SCTP_USERMODE) sctp_finish(); // pthread_exit(NULL); #endif return 0; }
void client_mode() { int i, error, stream, max_socket = 0; uint32_t ppid = 0; int client_socket[assoc_num]; char *message = "Awake"; fd_set rfds; struct timeval tv; stream = 1; printf("Running in Client Mode...\n"); /* Create the sockets */ for (i = 0; i < assoc_num; i++) { client_socket[i] = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); if (client_socket[i] < 0 ){ printf("Socket Failure: %s.\n", strerror(errno)); DUMP_CORE; } if (local_port) { error = bind(client_socket[i], &client_loop.sa, sizeof(client_loop)); if (error < 0) { printf("Bind Failure: %s\n", strerror(errno)); DUMP_CORE; } } printf("Create Socket #: %d\n", client_socket[i]); /* Connect to server and send initial message */ error = connect(client_socket[i], &server_loop.sa, sizeof(server_loop)); if (error < 0){ printf("Connect Failure: %s.\n", strerror(errno)); DUMP_CORE; } max_socket = client_socket[i]; ppid++; /* Send initial message */ error = sctp_sendmsg(client_socket[i], message, strlen(message) + 1, (struct sockaddr *)&server_loop, sizeof(server_loop), ppid, 0, stream, 0, 0); if (error < 0 ) { printf("Send Failure: %s.\n", strerror(errno)); DUMP_CORE; } } while (TRUE){ /* Clear the set for select() */ FD_ZERO(&rfds); /* Set time out values for select() */ tv.tv_sec = 5; tv.tv_usec = 0; /* Add the sockets select() will examine */ for (i = 0; i < assoc_num; i++) { FD_SET(client_socket[i], &rfds); } /* Wait until there is data to be read from one of the * sockets, or until the timer expires */ error = select(max_socket + 1, &rfds, NULL, NULL, &tv); if (error < 0) { printf("Select Failure: %s.\n", strerror(errno)); DUMP_CORE; } else if (error) { /* Loop through the array of sockets to find the ones *that have information to be read */ process_ready_sockets(client_socket, assoc_num, &rfds); } } }
int main() { int listenSock, connSock, ret, in , flags, i; struct sockaddr_in servaddr; struct sctp_initmsg initmsg; struct sctp_event_subscribe events; struct sctp_sndrcvinfo sndrcvinfo; //char buffer[MAX_BUFFER+1]; listenSock = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP ); bzero( (void *)&servaddr, sizeof(servaddr) ); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl( INADDR_ANY ); servaddr.sin_port = htons(MY_PORT_NUM); ret = bind( listenSock, (struct sockaddr *)&servaddr, sizeof(servaddr) ); /* Specify that a maximum of 5 streams will be available per socket */ memset( &initmsg, 0, sizeof(initmsg) ); initmsg.sinit_num_ostreams = 5; initmsg.sinit_max_instreams = 5; initmsg.sinit_max_attempts = 4; ret = setsockopt( listenSock, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg) ); listen( listenSock, 5 ); while( 1 ) { char buffer[MAX_BUFFER + 1]; int len ; printf("Awaiting a new connection\n"); connSock = accept( listenSock, (struct sockaddr *)NULL, NULL ); if(connSock == -1) die("accept()"); else printf("New client connected....\n"); in = sctp_recvmsg( connSock, (void *)buffer, sizeof(buffer), (struct sockaddr *)NULL, 0, &sndrcvinfo, &flags ); printf("%d\n", in); if (in <= 0) break; for (int i = 0; i < in; i++) { printf("%c", buffer[i]); } printf("\n"); char * out = new char[MAX_BUFFER + 1]; reverse_each(buffer, in, out); printf("%s\n", out); ret = sctp_sendmsg( connSock, (void *)out, (size_t)in, NULL, 0, 0, 0, 0, 0, 0 ); // printf("ret = %d\n", ret); delete(out); memset(buffer, '\0', sizeof(buffer)); close( connSock ); } return 0; }
int main(int argc, char **argv) { int opt, sock, newsock, result, flags, if_index = 0, on = 1; socklen_t sinlen, opt_len; struct sockaddr_storage sin; struct addrinfo hints, *res; struct sctp_sndrcvinfo sinfo; struct pollfd poll_fd; char getsockopt_peerlabel[1024]; char byte, *peerlabel, msglabel[1024], if_name[30]; bool nopeer = false, verbose = false, ipv4 = false, snd_opt = false; char *context, *host_addr = NULL, *bindx_addr = NULL; struct sockaddr_in ipv4_addr; unsigned short port; while ((opt = getopt(argc, argv, "4b:h:inv")) != -1) { switch (opt) { case '4': ipv4 = true; break; case 'b': bindx_addr = optarg; break; case 'h': host_addr = optarg; break; case 'i': snd_opt = true; break; case 'n': nopeer = true; break; case 'v': verbose = true; break; default: usage(argv[0]); } } if ((argc - optind) != 2) usage(argv[0]); port = atoi(argv[optind + 1]); if (!port) usage(argv[0]); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = AI_PASSIVE; hints.ai_protocol = IPPROTO_SCTP; if (ipv4) hints.ai_family = AF_INET; else hints.ai_family = AF_INET6; if (!strcmp(argv[optind], "stream")) hints.ai_socktype = SOCK_STREAM; else if (!strcmp(argv[optind], "seq")) hints.ai_socktype = SOCK_SEQPACKET; else usage(argv[0]); if (verbose) { if (getcon(&context) < 0) context = strdup("unavailable"); printf("Server process context: %s\n", context); free(context); } if (host_addr) { char *ptr; ptr = strpbrk(host_addr, "%"); if (ptr) strcpy(if_name, ptr + 1); if_index = if_nametoindex(if_name); if (!if_index) { perror("Server if_nametoindex"); exit(1); } result = getaddrinfo(host_addr, argv[optind + 1], &hints, &res); } else { result = getaddrinfo(NULL, argv[optind + 1], &hints, &res); } if (result < 0) { fprintf(stderr, "Server getaddrinfo: %s\n", gai_strerror(result)); exit(1); } sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sock < 0) { perror("Server socket"); exit(1); } result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (result < 0) { perror("Server setsockopt: SO_REUSEADDR"); close(sock); exit(1); } /* Enables sctp_data_io_events for sctp_recvmsg(3) for assoc_id. */ result = setsockopt(sock, SOL_SCTP, SCTP_EVENTS, &on, sizeof(on)); if (result < 0) { perror("Server setsockopt: SCTP_EVENTS"); close(sock); exit(1); } if (bindx_addr) { memset(&ipv4_addr, 0, sizeof(struct sockaddr_in)); ipv4_addr.sin_family = AF_INET; ipv4_addr.sin_port = htons(port); ipv4_addr.sin_addr.s_addr = inet_addr(bindx_addr); result = sctp_bindx(sock, (struct sockaddr *)&ipv4_addr, 1, SCTP_BINDX_ADD_ADDR); if (result < 0) { perror("Server sctp_bindx ADD - ipv4"); close(sock); exit(1); } } else { result = bind(sock, res->ai_addr, res->ai_addrlen); if (result < 0) { perror("Server bind"); close(sock); exit(1); } } if (verbose) { print_context(sock, "Server LISTEN"); print_ip_option(sock, ipv4, "Server LISTEN"); } if (listen(sock, SOMAXCONN)) { perror("Server listen"); close(sock); exit(1); } if (hints.ai_socktype == SOCK_STREAM) { if (verbose) print_context(sock, "Server STREAM"); do { socklen_t labellen = sizeof(getsockopt_peerlabel); sinlen = sizeof(sin); newsock = accept(sock, (struct sockaddr *)&sin, &sinlen); if (newsock < 0) { perror("Server accept"); close(sock); exit(1); } if (verbose) { print_context(newsock, "Server STREAM accept on newsock"); print_addr_info((struct sockaddr *)&sin, "Server connected to Client"); print_ip_option(newsock, ipv4, "Server STREAM accept on newsock"); } if (nopeer) { peerlabel = strdup("nopeer"); } else if (snd_opt) { peerlabel = get_ip_option(newsock, ipv4, &opt_len); if (!peerlabel) peerlabel = strdup("no_ip_options"); } else { result = getpeercon(newsock, &peerlabel); if (result < 0) { perror("Server getpeercon"); close(sock); close(newsock); exit(1); } /* Also test the getsockopt version */ result = getsockopt(newsock, SOL_SOCKET, SO_PEERSEC, getsockopt_peerlabel, &labellen); if (result < 0) { perror("Server getsockopt: SO_PEERSEC"); close(sock); close(newsock); exit(1); } if (verbose) printf("Server STREAM SO_PEERSEC peer label: %s\n", getsockopt_peerlabel); } printf("Server STREAM %s: %s\n", snd_opt ? "sock_opt" : "peer label", peerlabel); result = read(newsock, &byte, 1); if (result < 0) { perror("Server read"); close(sock); close(newsock); exit(1); } result = write(newsock, peerlabel, strlen(peerlabel)); if (result < 0) { perror("Server write"); close(sock); close(newsock); exit(1); } if (verbose) printf("Server STREAM sent: %s\n", peerlabel); free(peerlabel); /* Let the client close the connection first as this * will stop OOTB chunks if newsock closed early. */ poll_fd.fd = newsock; poll_fd.events = POLLRDHUP; poll_fd.revents = 1; result = poll(&poll_fd, 1, 1000); if (verbose && result == 1) printf("Server STREAM: Client closed connection\n"); else if (verbose && result == 0) printf("Server: poll(2) timed out - OKAY\n"); else if (result < 0) perror("Server - poll"); close(newsock); } while (1); } else { /* hints.ai_socktype == SOCK_SEQPACKET */ if (verbose) print_context(sock, "Server SEQPACKET sock"); do { sinlen = sizeof(sin); result = sctp_recvmsg(sock, msglabel, sizeof(msglabel), (struct sockaddr *)&sin, &sinlen, &sinfo, &flags); if (result < 0) { perror("Server sctp_recvmsg"); close(sock); exit(1); } if (verbose) { print_context(sock, "Server SEQPACKET recvmsg"); print_addr_info((struct sockaddr *)&sin, "Server SEQPACKET recvmsg"); print_ip_option(sock, ipv4, "Server SEQPACKET recvmsg"); } if (nopeer) { peerlabel = strdup("nopeer"); } else if (snd_opt) { peerlabel = get_ip_option(sock, ipv4, &opt_len); if (!peerlabel) peerlabel = strdup("no_ip_options"); } else { result = getpeercon(sock, &peerlabel); if (result < 0) { perror("Server getpeercon"); close(sock); exit(1); } } printf("Server SEQPACKET %s: %s\n", snd_opt ? "sock_opt" : "peer label", peerlabel); if (sin.ss_family == AF_INET6 && host_addr) ((struct sockaddr_in6 *)&sin)->sin6_scope_id = if_index; result = sctp_sendmsg(sock, peerlabel, strlen(peerlabel), (struct sockaddr *)&sin, sinlen, 0, 0, 0, 0, 0); if (result < 0) { perror("Server sctp_sendmsg"); close(sock); exit(1); } if (verbose) printf("Server SEQPACKET sent: %s\n", peerlabel); free(peerlabel); } while (1); } close(sock); exit(0); }
int main(int argc,char **argv) { int echo_to_all = 0; int ret_value; int sock_fd; int msg_flags; // 記錄要傳送訊息時的相關設定 char readbuf[BUFFERSIZE]; struct sockaddr_in servaddr,cliaddr; struct sctp_sndrcvinfo sri; // 記錄send, recv, association的相關資訊 struct sctp_event_subscribe evnts; int stream_increment = 1; socklen_t len; size_t rd_sz; // size_t指的就是unsigned long:rd_sz表示recv,send-size struct sockaddr *addrs; int addrcnt; int temp_step; if (argc == 2) { // 把字串轉換成數字 stream_increment = atoi(argv[1]); } // 建立socket的型態為SCTP的one-to-many的型態 sock_fd = socket(AF_INET,SOCK_SEQPACKET,IPPROTO_SCTP); if (sock_fd == -1) { printf("socket error\n"); exit(-1); } // 初始化server address的設定 memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); // 把socket與所建立的address綁在一起 ret_value = bind(sock_fd,(struct sockaddr *) &servaddr,sizeof(servaddr)); if (ret_value == -1) { printf("bind error\n"); exit(-1); } // Set up for notifications of internet bzero(&evnts,sizeof(evnts)); evnts.sctp_data_io_event = 1; // 使得sctp_sndrcvinfo可以伴隨資料傳送過來 ret_value = setsockopt(sock_fd,IPPROTO_SCTP,SCTP_EVENTS,&evnts,sizeof(evnts)); if (ret_value == -1) { printf("setsockopt error\n"); exit(-1); } // 設定等待多少個client端連線 ret_value = listen(sock_fd,LISTENQ); if (ret_value == -1) { printf("listen error\n"); exit(-1); } printf("start wait...\n"); for (;;) { len = sizeof(struct sockaddr_in); // 等待client端連線 rd_sz = sctp_recvmsg(sock_fd,readbuf,sizeof(readbuf),(struct sockaddr *) &cliaddr,&len,&sri,&msg_flags); // 分別印出local與peer端的address - start if ((addrcnt = sctp_getladdrs(sock_fd,sri.sinfo_assoc_id,&addrs))==-1) { printf("sctp_getladdrs error\n"); exit(-1); } printf("the local has %d address(es)\n",addrcnt); for (temp_step=0;temp_step<addrcnt;temp_step++) { printf("the address is %s\n",inet_ntoa(((struct sockaddr_in *) addrs+temp_step)->sin_addr)); } sctp_freeladdrs(addrs); if ((addrcnt = sctp_getpaddrs(sock_fd,sri.sinfo_assoc_id,&addrs))==-1) { printf("sctp_getpaddrs error\n"); exit(-1); } printf("the peer has %d address(es)\n",addrcnt); for (temp_step=0;temp_step<addrcnt;temp_step++) { printf("the address is %s\n",inet_ntoa(((struct sockaddr_in *) addrs+temp_step)->sin_addr)); } sctp_freepaddrs(addrs); // 分別印出local與peer端的address - start if (stream_increment) { sri.sinfo_stream++; if (sri.sinfo_stream >= 100) { sri.sinfo_stream = 0; } } // 把接收到的資料回送給client ret_value = sctp_sendmsg(sock_fd,readbuf,rd_sz,(struct sockaddr *) &cliaddr,len,sri.sinfo_ppid,sri.sinfo_flags,sri.sinfo_stream,0,0); if (ret_value == -1) { printf("sctp_sendmsg error\n"); exit(-1); } } return 0; }
int main(int argc, char **argv) { int fd, *cfdptr, c; size_t intlen; char *buffer; socklen_t addr_len; union sock_union{ struct sockaddr sa; struct sockaddr_in s4; struct sockaddr_in6 s6; } remote_addr; struct sockaddr_storage local_addr[MAX_LOCAL_ADDR]; char *local_addr_ptr = (char*) local_addr; unsigned int nr_local_addr = 0; struct timeval start_time, now, diff_time; int length, client; uint16_t local_port, remote_port, port; #ifdef SCTP_REMOTE_UDP_ENCAPS_PORT uint16_t udp_port = 0; struct sctp_udpencaps encaps; #endif double seconds; double throughput; const int on = 1; const int off = 0; int nodelay = 0; unsigned long i, number_of_messages; pthread_t tid; int rcvbufsize=0, sndbufsize=0, myrcvbufsize, mysndbufsize; struct linger linger; int fragpoint = 0; unsigned int timetolive = 0; unsigned int runtime = 0; struct sctp_setadaptation ind = {0}; #ifdef SCTP_AUTH_CHUNK unsigned int number_of_chunks_to_auth = 0; unsigned int chunk_number; unsigned char chunk[256]; struct sctp_authchunk sac; #endif struct sctp_assoc_value av; int unordered = 0; int ipv4only = 0; int ipv6only = 0; length = DEFAULT_LENGTH; number_of_messages = DEFAULT_NUMBER_OF_MESSAGES; port = DEFAULT_PORT; verbose = 0; very_verbose = 0; memset((void *) &remote_addr, 0, sizeof(remote_addr)); while ((c = getopt(argc, argv, "a:" #ifdef SCTP_AUTH_CHUNK "A:" #endif "Df:l:L:n:p:R:S:t:T:u" #ifdef SCTP_REMOTE_UDP_ENCAPS_PORT "U:" #endif "vV46")) != -1) switch(c) { case 'a': ind.ssb_adaptation_ind = atoi(optarg); break; #ifdef SCTP_AUTH_CHUNK case 'A': if (number_of_chunks_to_auth < 256) { chunk[number_of_chunks_to_auth++] = (unsigned char)atoi(optarg); } break; #endif case 'D': nodelay = 1; break; case 'f': fragpoint = atoi(optarg); break; case 'l': length = atoi(optarg); break; case 'L': if (nr_local_addr < MAX_LOCAL_ADDR) { struct sockaddr_in *s4 = (struct sockaddr_in*) local_addr_ptr; struct sockaddr_in6 *s6 = (struct sockaddr_in6*) local_addr_ptr; if (inet_pton(AF_INET6, optarg, &s6->sin6_addr)) { s6->sin6_family = AF_INET6; #ifdef HAVE_SIN_LEN s6->sin6_len = sizeof(struct sockaddr_in6); #endif local_addr_ptr += sizeof(struct sockaddr_in6); nr_local_addr++; } else { if (inet_pton(AF_INET, optarg, &s4->sin_addr)) { s4->sin_family = AF_INET; #ifdef HAVE_SIN_LEN s4->sin_len = sizeof(struct sockaddr_in); #endif local_addr_ptr += sizeof(struct sockaddr_in); nr_local_addr++; } else { printf("Invalid address\n"); fprintf(stderr, "%s", Usage); exit(1); } } } break; case 'n': number_of_messages = atoi(optarg); break; case 'p': port = atoi(optarg); break; case 'R': rcvbufsize = atoi(optarg); break; case 'S': sndbufsize = atoi(optarg); break; case 't': timetolive = atoi(optarg); break; case 'T': runtime = atoi(optarg); number_of_messages = 0; break; case 'u': unordered = 1; break; #ifdef SCTP_REMOTE_UDP_ENCAPS_PORT case 'U': udp_port = atoi(optarg); break; #endif case 'v': verbose = 1; break; case 'V': verbose = 1; very_verbose = 1; break; case '4': ipv4only = 1; if (ipv6only) { printf("IPv6 only already\n"); exit(1); } break; case '6': ipv6only = 1; if (ipv4only) { printf("IPv4 only already\n"); exit(1); } break; default: fprintf(stderr, "%s", Usage); exit(1); } if (optind == argc) { client = 0; local_port = port; remote_port = 0; } else { client = 1; local_port = 0; remote_port = port; } if (nr_local_addr == 0) { memset((void *) local_addr, 0, sizeof(local_addr)); if (ipv4only) { struct sockaddr_in *s4 = (struct sockaddr_in*) local_addr; s4->sin_family = AF_INET; #ifdef HAVE_SIN_LEN s4->sin_len = sizeof(struct sockaddr_in); #endif s4->sin_addr.s_addr = htonl(INADDR_ANY); } else { struct sockaddr_in6 *s6 = (struct sockaddr_in6*) local_addr; s6->sin6_family = AF_INET6; #ifdef HAVE_SIN_LEN s6->sin6_len = sizeof(struct sockaddr_in6); #endif s6->sin6_addr = in6addr_any; } nr_local_addr = 1; } local_addr_ptr = (char*) local_addr; for (i = 0; i < nr_local_addr; i++) { struct sockaddr_in *s4 = (struct sockaddr_in*) local_addr_ptr; struct sockaddr_in6 *s6 = (struct sockaddr_in6*) local_addr_ptr; if (s4->sin_family == AF_INET) { s4->sin_port = htons(local_port); local_addr_ptr += sizeof(struct sockaddr_in); if (ipv6only) { printf("Can't use IPv4 address when IPv6 only\n"); exit(1); } } else if (s6->sin6_family == AF_INET6) { s6->sin6_port = htons(local_port); local_addr_ptr += sizeof(struct sockaddr_in6); if (ipv4only) { printf("Can't use IPv6 address when IPv4 only\n"); exit(1); } } } if ((fd = socket((ipv4only ? AF_INET : AF_INET6), SOCK_STREAM, IPPROTO_SCTP)) < 0) perror("socket"); if (!ipv4only) { if (ipv6only) { if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&on, (socklen_t)sizeof(on)) < 0) perror("ipv6only"); } else { if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*)&off, (socklen_t)sizeof(off)) < 0) perror("ipv6only"); } } #ifdef SCTP_AUTH_CHUNK for (chunk_number = 0; chunk_number < number_of_chunks_to_auth; chunk_number++) { sac.sauth_chunk = chunk[chunk_number]; if (setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &sac, (socklen_t)sizeof(struct sctp_authchunk)) < 0) perror("setsockopt"); } #endif if (ind.ssb_adaptation_ind > 0) { if (setsockopt(fd, IPPROTO_SCTP, SCTP_ADAPTATION_LAYER, (const void*)&ind, (socklen_t)sizeof(struct sctp_setadaptation)) < 0) { perror("setsockopt"); } } if (!client) { setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*)&on, (socklen_t)sizeof(on)); } #ifdef SCTP_REMOTE_UDP_ENCAPS_PORT memset(&encaps, 0, sizeof(struct sctp_udpencaps)); encaps.sue_address.ss_family = (ipv4only ? AF_INET : AF_INET6); encaps.sue_port = htons(udp_port); if (setsockopt(fd, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) { perror("setsockopt"); } #endif if (nr_local_addr > 0) { if (sctp_bindx(fd, (struct sockaddr *)local_addr, nr_local_addr, SCTP_BINDX_ADD_ADDR) != 0) perror("bind"); } if (!client) { struct sctp_event_subscribe event; if (listen(fd, 100) < 0) perror("listen"); if (rcvbufsize) if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbufsize, sizeof(int)) < 0) perror("setsockopt: rcvbuf"); if (verbose) { intlen = sizeof(int); if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &myrcvbufsize, (socklen_t *)&intlen) < 0) { perror("setsockopt: rcvbuf"); } else { fprintf(stdout,"Receive buffer size: %d.\n", myrcvbufsize); } } memset(&event, 0, sizeof(event)); event.sctp_data_io_event=1; if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) != 0) { perror("set event failed"); } while (1) { memset(&remote_addr, 0, sizeof(remote_addr)); if (ipv4only) { addr_len = sizeof(struct sockaddr_in); } else { addr_len = sizeof(struct sockaddr_in6); } cfdptr = malloc(sizeof(int)); if ((*cfdptr = accept(fd, (struct sockaddr *)&remote_addr, &addr_len)) < 0) { perror("accept"); continue; } if (verbose) { char temp[INET6_ADDRSTRLEN]; if (remote_addr.sa.sa_family == AF_INET) { fprintf(stdout,"Connection accepted from %s:%d\n", inet_ntop(AF_INET, &remote_addr.s4.sin_addr, temp, INET_ADDRSTRLEN), ntohs(remote_addr.s4.sin_port)); } else { fprintf(stdout,"Connection accepted from %s:%d\n", inet_ntop(AF_INET6, &remote_addr.s6.sin6_addr, temp, INET6_ADDRSTRLEN), ntohs(remote_addr.s6.sin6_port)); } } pthread_create(&tid, NULL, &handle_connection, (void *) cfdptr); } close(fd); } else { if (inet_pton(AF_INET6, argv[optind], &remote_addr.s6.sin6_addr)) { remote_addr.s6.sin6_family = AF_INET6; #ifdef HAVE_SIN_LEN remote_addr.s6.sin6_len = sizeof(struct sockaddr_in6); #endif remote_addr.s6.sin6_port = htons(remote_port); addr_len = sizeof(struct sockaddr_in6); if (ipv4only) { printf("Can't use IPv6 address when IPv4 only\n"); exit(1); } } else { if (inet_pton(AF_INET, argv[optind], &remote_addr.s4.sin_addr)) { remote_addr.s4.sin_family = AF_INET; #ifdef HAVE_SIN_LEN remote_addr.s4.sin_len = sizeof(struct sockaddr_in); #endif remote_addr.s4.sin_port = htons(remote_port); addr_len = sizeof(struct sockaddr_in); if (ipv6only) { printf("Can't use IPv4 address when IPv6 only\n"); exit(1); } } else { printf("Invalid address\n"); fprintf(stderr, "%s", Usage); exit(1); } } if (fragpoint) { av.assoc_id = 0; av.assoc_value = fragpoint; if (setsockopt(fd, IPPROTO_SCTP, SCTP_MAXSEG, &av, sizeof(av)) < 0) { perror("setsockopt: SCTP_MAXSEG"); } } if (connect(fd, (struct sockaddr *)&remote_addr, addr_len) < 0) { perror("connect"); } #ifdef SCTP_NODELAY /* Explicit settings, because LKSCTP does not enable it by default */ if (nodelay == 1) { if (setsockopt(fd, IPPROTO_SCTP, SCTP_NODELAY, (char *)&on, sizeof(on)) < 0) { perror("setsockopt: nodelay"); } } else { if (setsockopt(fd, IPPROTO_SCTP, SCTP_NODELAY, (char *)&off, sizeof(off)) < 0) { perror("setsockopt: nodelay"); } } #endif if (sndbufsize) if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbufsize, sizeof(int)) < 0) { perror("setsockopt: sndbuf"); } if (verbose) { intlen = sizeof(int); if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &mysndbufsize, (socklen_t *)&intlen) < 0) { perror("setsockopt: sndbuf"); } else { fprintf(stdout,"Send buffer size: %d.\n", mysndbufsize); } } buffer = malloc(length); memset(buffer, 'A', length); gettimeofday(&start_time, NULL); if (verbose) { printf("Start sending %ld messages...", (long)number_of_messages); fflush(stdout); } i = 0; done = 0; if (runtime > 0) { signal(SIGALRM, stop_sender); alarm(runtime); } while (!done && ((number_of_messages == 0) || (i < (number_of_messages - 1)))) { if (very_verbose) { printf("Sending message number %lu.\n", i); } if (sctp_sendmsg(fd, buffer, length, NULL, 0, 0, unordered?SCTP_UNORDERED:0, 0, timetolive, 0) < 0) { perror("sctp_sendmsg"); break; } i++; } if (sctp_sendmsg(fd, buffer, length, NULL, 0, 0, unordered?SCTP_EOF|SCTP_UNORDERED:SCTP_EOF, 0, timetolive, 0) < 0) { perror("sctp_sendmsg"); } i++; if (verbose) printf("done.\n"); linger.l_onoff = 1; linger.l_linger = LINGERTIME; if (setsockopt(fd, SOL_SOCKET, SO_LINGER,(char*)&linger, sizeof(struct linger)) < 0) { perror("setsockopt"); } close(fd); gettimeofday(&now, NULL); timersub(&now, &start_time, &diff_time); seconds = diff_time.tv_sec + (double)diff_time.tv_usec/1000000; fprintf(stdout, "%s of %ld messages of length %u took %f seconds.\n", "Sending", i, length, seconds); throughput = (double)i * (double)length / seconds; fprintf(stdout, "Throughput was %f Byte/sec.\n", throughput); } return 0; }
void * pe_thread(void *thrid) { int tid; tid = (int)thrid; int listenSock, connSock, ret; struct sockaddr_in servaddr; struct sockaddr_in fromaddr; socklen_t socklen; struct sctp_initmsg initmsg; char buffer[MAX_BUFFER]; char rcvbuf[MAX_BUFFER]; printf("\t\t\tHello World! It's me, thread #%d!\n", tid); bzero((void *)rcvbuf, MAX_BUFFER); socklen = sizeof(struct sockaddr_in); /* Create SCTP TCP-Style Socket */ listenSock = socket( AF_INET, SOCK_STREAM, IPPROTO_SCTP ); /* Accept connections from any interface */ bzero( (void *)&servaddr, sizeof(servaddr) ); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl( INADDR_ANY ); servaddr.sin_port = htons(MY_PORT_NUM); ret = bind( listenSock, (struct sockaddr *)&servaddr, sizeof(servaddr) ); printf("Listening on port: 0x%x\n", servaddr.sin_port); /* Specify that a maximum of 5 streams will be available per socket */ memset( &initmsg, 0, sizeof(initmsg) ); initmsg.sinit_num_ostreams = 5; initmsg.sinit_max_instreams = 5; initmsg.sinit_max_attempts = 4; ret = setsockopt( listenSock, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg) ); /* Place the server socket into the listening state */ listen( listenSock, 5 ); /* Server loop... */ while( 1 ) { /* Await a new client connection */ printf("Awaiting a new connection\n"); connSock = accept(listenSock, (struct sockaddr *)NULL, (socklen_t *)NULL); printf("Client Connected \n"); /* New client socket has connected */ ret = sctp_recvmsg(connSock, rcvbuf, MAX_BUFFER, (struct sockaddr *)&fromaddr, &socklen, NULL, 0); if (ret < 0) { perror("Error getting data"); exit(1); } rcvbuf[ret] = '\0'; printf("Got [%s]\n", rcvbuf); /* Send local time on stream 0 (local time stream) */ snprintf(buffer, MAX_BUFFER, "I got [%s] from you", rcvbuf); printf("Sending [%s]\n",buffer); ret = sctp_sendmsg(connSock, (void *)buffer, (size_t)strlen(buffer), NULL, 0, 0, 0, LOCALTIME_STREAM, 0, 0 ); if (ret < 0) { perror("Error sending msg"); exit(1); } /* Close the client connection */ sleep(10); close( connSock ); } pthread_exit(NULL); }
int run_test_client(int argc, char* argv[]) { int sctp_sock = -1, gai_stat = 0; // socket struct sockaddr_storage server_addr; // server address structure struct sockaddr_storage peer_addr; // peer address structure // Lengths for address structures socklen_t server_addr_len = 0; socklen_t peer_addr_len = 0; struct sctp_event_subscribe sctp_events; // sctp events struct sctp_sndrcvinfo infodata; // sctp sender info struct addrinfo hints,*ai = NULL,*iter = NULL; // for getaddrinfo // invalid amount of parameters if(argc != 3) return testclient_input_error((argc == 1) ? argv[0] : NULL); // Use stroull for larger numbers, atoi() can be used for short ints unsigned int port = strtoull(argv[2],NULL,10); printf("connecting to: %s %u\n",argv[1],port); memset(&server_addr,0,sizeof(struct sockaddr_storage)); // Get the server address structure with getaddrinfo() memset(&hints,0,sizeof(hints)); hints.ai_family = PF_UNSPEC; // To allow IPv4 or IPv6 hints.ai_protocol = IPPROTO_SCTP; // SCTP protocol supported hints.ai_socktype = SOCK_SEQPACKET; // Get (and set) server info if((gai_stat = getaddrinfo(argv[1],argv[2],&hints,&ai)) < 0) { fprintf(stderr, "Cannot resolve: "); print_addr_type(argv[1]); fprintf(stderr, "Error: %s\n",gai_strerror(gai_stat)); if(ai) freeaddrinfo(ai); return -1; } // Use the first of the returned addresses for(iter = ai; iter != NULL; iter = iter->ai_next) { // To allow the usage of both use IPv6 type for socket, create socket for SCTP if((sctp_sock = socket(iter->ai_family, iter->ai_socktype, iter->ai_protocol)) < 0) { perror("socket()"); if(ai) freeaddrinfo(ai); return -1; } // Note that we do not need connect() with SCTP #ifdef USE_CONNECT #if USE_CONNECT == 1 if(connect(sctp_sock,(SA*)&server_addr,server_addr_len) < 0 ) perror("connect"); else printf("connected\n"); #endif #endif memcpy(&server_addr,iter->ai_addr,iter->ai_addrlen); server_addr_len = iter->ai_addrlen; break; } freeaddrinfo(ai); // No need for this anymore // Allow to receive events from SCTP stack memset(&sctp_events,0,sizeof(sctp_events)); set_sctp_events(&sctp_events); if(setsockopt(sctp_sock, IPPROTO_SCTP, SCTP_EVENTS, &sctp_events, sizeof(sctp_events)) < 0) perror("setsockopt"); int byte_count = 513; char* data_to_send = testclient_fill_random_data(byte_count); // create some data to send int sent_bytes = sctp_sendmsg(sctp_sock, // socket file descriptor data_to_send, // Data to send byte_count, // Amount of data to send in bytes (SA*)&server_addr, // address of receiver server_addr_len, // length of address structure 666, // Protocol payload identifier 0, // flags 2, // stream id 0, // time to live, 0 = infinite 0); printf("Sent %d bytes\n", sent_bytes); int recv_flags = 0; int read_bytes = 0; /* Read until something is received from peer (server) just for demonstrative purposes Use select() in your code */ while(1) { memset(data_to_send,0,byte_count); // clear the buffer so new data can be written to it memset(&infodata,0,sizeof(infodata)); recv_flags = 0; memset(&peer_addr,0,sizeof(peer_addr)); read_bytes = sctp_recvmsg(sctp_sock, data_to_send, byte_count, (SA*)&peer_addr, &peer_addr_len, &infodata, &recv_flags); if(read_bytes > 0) { // Is a SCTP notification if(recv_flags & MSG_NOTIFICATION) { printf("Got notification: "); check_sctp_event(data_to_send,read_bytes); printf("\n"); } // Otherwise data is received from peer else { printf("Got %d bytes on stream %d\n", read_bytes,infodata.sinfo_stream); break; // Got data, expecting 1 packet (ignore further notifications) -> break } } else break; } free(data_to_send); sleep(5); data_to_send = testclient_fill_random_data(byte_count); // We can send data also with sendto() when SCTP is used ! sent_bytes = sendto(sctp_sock, // socket file descriptor data_to_send, // Data to send byte_count, // Amount of data to send in bytes 0, // Flags (SA*)&server_addr, // address of receiver server_addr_len // length of address structure ); printf("Sent %d bytes\n", sent_bytes); while(1) { memset(&infodata,0,sizeof(infodata)); recv_flags = 0; memset(&peer_addr,0,sizeof(peer_addr)); memset(data_to_send,0,byte_count); read_bytes = sctp_recvmsg(sctp_sock, data_to_send, byte_count, (SA*)&peer_addr, &peer_addr_len, &infodata, &recv_flags); if(read_bytes > 0) { // Is a SCTP notification if(recv_flags & MSG_NOTIFICATION) { printf("Got notification: "); check_sctp_event(data_to_send,read_bytes); printf("\n"); } // Otherwise data is received from peer else { printf("Got %d bytes on stream %d\n", read_bytes,infodata.sinfo_stream); break; // Got data, expecting 1 packet (ignore further notifications) -> break } } else break; } free(data_to_send); close(sctp_sock); return 0; }
int main(int argc, char** argv) { struct addrinfo hints; struct addrinfo* addressInfo = NULL; int i; int retVal; int optval; int serverSocket; struct sockaddr_storage clientAddress; struct AddrPortStrings clientAddrPortStrings; struct sctp_event_subscribe events; char buffer[2000]; struct sctp_sndrcvinfo sndrcvinfo; int flags; socklen_t clientAddressSize; if (argc != 3) { printf("Usage: %s <address> <port>\n", argv[0]); return 1; } memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_SEQPACKET; hints.ai_protocol = IPPROTO_SCTP; hints.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG); if (retVal = getaddrinfo(argv[1], argv[2], &hints, &addressInfo) != 0) { printf("getaddrinfo failed, retVal = %d\n", retVal); return 1; } serverSocket = socket(addressInfo->ai_family, addressInfo->ai_socktype, addressInfo->ai_protocol); if (serverSocket < 0) { printf("error creating serverSocket, errno = %d\n", errno); return 1; } printf("created serverSocket %d\n", serverSocket); optval = 1; if (setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) { printf("error setting SO_REUSEADDR errno = %d\n", errno); return 1; } retVal = bind(serverSocket, addressInfo->ai_addr, addressInfo->ai_addrlen); if (retVal < 0) { printf("bind failed, errno = %d\n", errno); return 1; } if (listen(serverSocket, SOMAXCONN) < 0) { printf("listen failed, errno = %d\n", errno); return 1; } memset(&events, 1, sizeof(events)); retVal = setsockopt(serverSocket, SOL_SCTP, SCTP_EVENTS, &events, sizeof(events)); if (retVal < 0) { printf("setsockopt(SCTP_EVENTS) error errno = %d\n", errno); return 1; } printLocalAddresses(serverSocket); while (1) { flags = 0; clientAddressSize = sizeof(clientAddress); printf("before sctp_recvmsg\n"); retVal = sctp_recvmsg(serverSocket, buffer, 2000, (struct sockaddr*)&clientAddress, &clientAddressSize, &sndrcvinfo, &flags); printf("sctp_recvmsg returns %d\n", retVal); if (retVal < 0) { printf("errno = %d\n", errno); } else if (flags & MSG_NOTIFICATION) { printf("got MSG_NOTIFICATION\n"); printSctpNotification((union sctp_notification*)buffer); } else if (flags & MSG_EOR) { printf("got MSG_EOR\n"); if (addressToNameAndPort( (struct sockaddr*)&clientAddress, clientAddressSize, &clientAddrPortStrings) < 0) { continue; } printf("received message length %d from client %s:%s\n", retVal, clientAddrPortStrings.addrString, clientAddrPortStrings.portString); printf("call sctp_sendmsg\n"); retVal = sctp_sendmsg(serverSocket, buffer, retVal, (struct sockaddr*)&clientAddress, clientAddressSize, 0, 0, 0, 0, 0); printf("sctp_sendmsg returns %d\n", retVal); } } return 0; }
int main(int argc,char **argv) { int echo_to_all = 0; int ret_value; int sock_fd; int msg_flags; // 記錄要傳送訊息時的相關設定 char readbuf[BUFFERSIZE]; struct sockaddr_in servaddr,cliaddr; struct sctp_sndrcvinfo sri; // 記錄send, recv, association的相關資訊 struct sctp_event_subscribe evnts; int stream_increment = 1; socklen_t len; size_t rd_sz; // size_t指的就是unsigned long struct sctp_initmsg initm; if (argc == 2) { // 把字串轉換成數字 stream_increment = atoi(argv[1]); } // 建立socket的型態為SCTP的one-to-many的型態 sock_fd = socket(AF_INET,SOCK_SEQPACKET,IPPROTO_SCTP); if (sock_fd == -1) { printf("socket error\n"); exit(-1); } // 預設是10條stream,設定為30條 memset(&initm,0,sizeof(initm)); initm.sinit_num_ostreams = SERV_MORE_STRMS_SCTP; setsockopt(sock_fd,IPPROTO_SCTP,SCTP_INITMSG,&initm,sizeof(initm)); // 初始化server address的設定 memset(&servaddr,0,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); // 把socket與所建立的address綁在一起 ret_value = bind(sock_fd,(struct sockaddr *) &servaddr,sizeof(servaddr)); if (ret_value == -1) { printf("bind error\n"); exit(-1); } // Set up for notifications of internet bzero(&evnts,sizeof(evnts)); evnts.sctp_data_io_event = 1; // 監控sctp的data的io事件:1是打開的意思 ret_value = setsockopt(sock_fd,IPPROTO_SCTP,SCTP_EVENTS,&evnts,sizeof(evnts)); if (ret_value == -1) { printf("setsockopt error\n"); exit(-1); } // 設定等待多少個client端連線 ret_value = listen(sock_fd,LISTENQ); if (ret_value == -1) { printf("listen error\n"); exit(-1); } printf("start wait...\n"); for (;;) { len = sizeof(struct sockaddr_in); // 等待client端連線 rd_sz = sctp_recvmsg(sock_fd,readbuf,sizeof(readbuf),(struct sockaddr *) &cliaddr,&len,&sri,&msg_flags); if (stream_increment) { sri.sinfo_stream++; if (sri.sinfo_stream >= 100) { sri.sinfo_stream = 0; } } // 把接收到的資料回送給client ret_value = sctp_sendmsg(sock_fd,readbuf,rd_sz,(struct sockaddr *) &cliaddr,len,sri.sinfo_ppid,sri.sinfo_flags,sri.sinfo_stream,0,0); if (ret_value == -1) { printf("sctp_sendmsg error\n"); exit(-1); } } return 0; }
int main() { int listenSock, connSock, ret; struct sockaddr_in servaddr; struct sctp_initmsg initmsg; char buffer[MAX_BUFFER+1]; time_t currentTime; // ignore SIGPIPE signal(SIGPIPE, SIG_IGN); // Create SCTP TCP-Style Socket listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); // Accept connections from any interface bzero((void *)&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(MY_PORT_NUM); ret = bind(listenSock, (struct sockaddr *)&servaddr, sizeof(servaddr)); // Specify that a maximum of 5 streams will be available per socket memset(&initmsg, 0, sizeof(initmsg)); initmsg.sinit_num_ostreams = 5; initmsg.sinit_max_instreams = 5; initmsg.sinit_max_attempts = 4; ret = setsockopt(listenSock, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg)); // Place the server socket into the listening state listen(listenSock, 5); printf("Listening on 0.0.0.0:%d ...\n", MY_PORT_NUM); while(1) { connSock = accept(listenSock, (struct sockaddr *)NULL, (socklen_t *)NULL); printf("Accepted a new connection: %d\n", connSock); // Grab the current time currentTime = time(NULL); // Send local time on stream LOCALTIME_STREAM snprintf(buffer, MAX_BUFFER, "%s", ctime(¤tTime)); ret = sctp_sendmsg(connSock, (void *)buffer, (size_t)strlen(buffer), NULL, 0, 0, 0, LOCALTIME_STREAM, 0, 0); if(ret == -1) { printf("sctp_sendmsg error: %s\n", strerror(errno)); close(connSock); continue; } // Send GMT on stream GMT_STREAM snprintf(buffer, MAX_BUFFER, "%s", asctime(gmtime(¤tTime))); ret = sctp_sendmsg(connSock, (void *)buffer, (size_t)strlen(buffer), NULL, 0, 0, 0, GMT_STREAM, 0, 0); if(ret == -1) { printf("sctp_sendmsg error: %s\n", strerror(errno)); close(connSock); continue; } close(connSock); } return 0; }