Dear all,
I tried to create the small program to understand how client and server
work on SCTP. I created two different kinds of program, one is for 1 to
1 sctp socket and another is 1 to many socket. The first one, 1 to 1
socket, is working well but the second one.
My program for the 1 to many socket is that client send the data to the
server to establish the connecttion with sctp_sendsmg() and the server
calls sctp_rcvmsg() to receive the data from the client. This is still
fine. But the problem is when server want to send data back to client,
the error is shown. The error message from strerror (errno) is "Address
already in use".
Could someone tell me what is wrong with my program?
#include <stdio.h>
#include <strings.h>
#include <iostream.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/sctp.h>
#include <sys/uio.h>
#include <stdlib.h>
#define BACKLOG 5
#define SERV_PORT 47123
#define MAX_MSG 100
#define MSG_SIZE (MAX_MSG+1)
#define AUTO_CLOSING_TIME 60
#define SERV_IP htonl(0x7f000001)
int main(){
struct sockaddr_in servaddr, clientaddr;
int sockfd, confd, msg_flags;
socklen_t len;
char str[16];
char line[MSG_SIZE];
struct sctp_event_subscribe events;
struct sctp_sndrcvinfo sockinfo;
// To creat a 1 to M SCTP socket
sockfd = ::socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
if(sockfd < 0){
char* errmsg = strerror (errno);
cout << "Creating socket is failed : " << errmsg <<"\n";
return 0;
}
else{
cout << "Creating socket is successful : " << sockfd <<"\n";
}
// To bind a primary IP address to the socket
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("192.168.139.94");
servaddr.sin_port = htons (SERV_PORT);
if(::bind(sockfd, (struct sockaddr*) &servaddr, sizeof(servaddr) ) <
0){
char* errmsg = strerror (errno);
cout << "Binding Address to socket is failed : " << errmsg <<"\n";
return 0;
}
else{
cout << "Binding Address to socket is successful with" << "\n";
}
// To bind more IP addresses to the socket
struct sockaddr_in addrset[2];
for (int i = 0; i < 2; i++) {
addrset[i].sin_family = AF_INET;
addrset[i].sin_port = htons(SERV_PORT);
}
addrset[0].sin_addr.s_addr = inet_addr("192.168.139.93");
addrset[1].sin_addr.s_addr = SERV_IP;
if(sctp_bindx(sockfd, (struct sockaddr*) &addrset[0], 2,
SCTP_BINDX_ADD_ADDR) < 0){
char* errmsg = strerror (errno);
cout << "Binding more addresses is failed : " << errmsg <<"\n";
}
else{
cout << "Binding more addresses is successful\n";
}
bzero (&events, sizeof (events)) ;
events.sctp_data_io_event = 1;
if(::setsockopt(sockfd, IPPROTO_SCTP, SCTP_EVENTS, &events,
sizeof(events) ) < 0){
char* errmsg = strerror (errno);
cout << "Setting data io option is failed : " << errmsg <<"\n";
return 0;
}
else{
cout << "Setting data io option is successful"<< "\n";
}
if(::listen (sockfd, BACKLOG) < 0){
char* errmsg = strerror (errno);
cout << "Listenning is failed : " << errmsg <<"\n";
return 0;
}
else{
cout << "Listenning is successful\n";
}
while(true){
cout << "Waiting for SCTP connection on port " << SERV_PORT << "
....\n";
memset(line, 0x0, MSG_SIZE);
while (true) {
int recv_msg_size = sctp_recvmsg(sockfd, line, sizeof(line),
(struct sockaddr*) &clientaddr, &len, &sockinfo, &msg_flags );
if(recv_msg_size < 0){
char* errmsg = strerror (errno);
cerr << "Error: cannot send data: " << errmsg <<"\n";
}
else{
cout << "---" << line << "----\n";
cout << "---" << sizeof(line) <<" : "<< recv_msg_size << "----\n";
cout << "---" << inet_ntoa(clientaddr.sin_addr) << "----\n";
cout << "---" << ntohs(clientaddr.sin_port)<< "----\n";
cout << "---" << sockinfo.sinfo_assoc_id << "----\n";
cout << "---" << sockinfo.sinfo_stream << "----\n";
}
sockinfo.sinfo_stream++;
if (::sctp_sendmsg(sockfd, line, sizeof(line), (struct
sockaddr*) &clientaddr, len, sockinfo.sinfo_ppid, sockinfo.sinfo_flags,
sockinfo.sinfo_stream, 0, 0) < 0){
char* errmsg = strerror (errno);
cerr << "Error: cannot send data: " << errmsg <<"\n";
switch(errno){
case EWOULDBLOCK : cout << "The socket is marked nonblocking and
the requested operation would block.\n";
case EBADF: cout << "The s argument is an invalid file
descriptor.\n";
case ENOTSOCK : cout << "The s argument is not a socket.\n";
case EDESTADDRREQ : cout << "A destination address is
required.\n";
case EOPNOTSUPP : cout << "MSG_OOB is set as a flag.\n";
case ENOBUFS : cout << "The system couldn't allocate an internal
buffer. The operation may succeed when buffers become available.\n";
case EPIPE : cout << "The socket is shutting down and no more
writes are allowed.\n";
case ENOTCONN : cout << "There is no established association.\n";
case EINVAL : cout << "Control message length is incorrect.\n";
case EFAULT : cout << "An invalid user space address was specified
for a parameter.\n";
case EMSGSIZE : cout << "The socket requires that the message be
sent atomically, but the size of the message made this impossible.\n";
case EAFNOSUPPORT : cout << "Address family of the specified
destination address is other than AF_INET or AF_INET6.\n";
default: cout << "Error without any reason.\n";
}
}
memset(line, 0x0, MSG_SIZE); // set line to all zeroes
}
}
if (::close(sockfd) < 0){
char* errmsg = strerror (errno);
cout << "Socket closing is failed : " << errmsg <<"\n";
}
else{
cout << "Socket closing is successful\n";
}
return 0;
}
Thank you