// サーバーモードにする。一度だけ実行可能。 SOCKET MikanSocket::CreateServer( unsigned short port, int connect, int type ) { struct sockaddr_in server; int yes; if ( mode != MIKAN_SOCKET_MODE_NONE ) { return INVALID_SOCKET; } if ( type != MIKAN_SOCKET_NONE ) { SetType( type ); } mode = MIKAN_SOCKET_MODE_SERVER; connect_max = connect; // ソケットの設定。 server.sin_port = this->port = htons( port ); server.sin_family = AF_INET;//AF_INET6 server.sin_addr.S_un.S_addr = INADDR_ANY; sock = ssock = CreateSocket( GetSocketType(), server.sin_family, 0 ); if ( sock == INVALID_SOCKET ) { return INVALID_SOCKET; } // bind時のtime_waitによるエラー回避。 setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&yes, sizeof( int ) ); if ( bind( sock, ( struct sockaddr * )&server, sizeof( struct sockaddr_in ) ) != 0 ) { // bindエラー。 return INVALID_SOCKET; } // TCPサーバーの場合はlistenする。 if ( GetSocketType() == MIKAN_SOCKET_TCP && listen( sock, connect_max ) != 0 ) { // listenエラー。 return INVALID_SOCKET; } return sock; }
int MikanSocket::Send( const char *data, int size ) { struct sockaddr_in addrin; int loadedsize; int yes; if ( sock == INVALID_SOCKET ) { return -1; } switch ( GetSocketType() ) { case MIKAN_SOCKET_TCP: return send( sock, data, size, 0 ); case MIKAN_SOCKET_UDP: // すでに設定済みの相手に送る。 addrin.sin_family = addr.sin_family; addrin.sin_port = addr.sin_port; addrin.sin_addr.S_un.S_addr = addr.sin_addr.S_un.S_addr; if ( type == MIKAN_SOCKET_BROADCAST ) { // ソケットにブロードキャストの属性を付ける。 setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (char *)&yes, sizeof( yes ) ); } loadedsize = sendto( sock, data, size, 0, ( struct sockaddr * )&addrin, sizeof( struct sockaddr_in ) );//sizeof(addr) ); loadsize += loadedsize; return loadedsize; } return 0; }
void Messenger::SwitchClientType(int sid, SocketType type) { try { fSocketsConnected.erase (std::pair<int,SocketType>(sid, GetSocketType(sid))); fSocketsConnected.insert(std::pair<int,SocketType>(sid, type)); } catch (Exception& e) { e.Dump(); } }
int MikanSocket::Receive( char *buf, int size, struct sockaddr *from ) { int len = 0; int fromsize; if ( sock == INVALID_SOCKET ) { return -1; } if ( GetSocketType() == MIKAN_SOCKET_TCP || from == NULL ) { len = recv( sock, buf, size, 0 ); } else if ( GetSocketType() == MIKAN_SOCKET_UDP ) { fromsize = sizeof( sockaddr ); len = recvfrom( sock, buf, size, 0, from, &fromsize ); } loadsize += len; return len; }
void Messenger::DisconnectClient(int sid, MessageKey key, bool force) { SocketType type; try { type = GetSocketType(sid); } catch (Exception& e) { e.Dump(); return; } std::ostringstream o; o << "Disconnecting client # " << sid; PrintInfo(o.str()); Socket s; s.SetSocketId(sid); s.Stop(); fSocketsConnected.erase(std::pair<int,SocketType>(sid, type)); FD_CLR(sid, &fMaster); }
//------------------------------------------------------------------------------ // // SetMulticast() // //------------------------------------------------------------------------------ bool TDSocket::SetMulticast(bool bEnable, u8 multicastTTL) { bool bRetVal = false; if (GetSocketType() == TDSocket::SocketTypeUdp) { m_bIsMulticast = bEnable; if (SETSOCKOPT(m_socket, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&multicastTTL, sizeof(multicastTTL)) == SocketError) { TranslateSocketError(); bRetVal = false; } else { bRetVal = true; } } else { m_socketErrno = TDSocket::SocketProtocolError; } return bRetVal; }
char * MikanSocket::Receive( int *getsize, struct sockaddr *from ) { int len = 0, head = 0, fromsize; char * buf; if ( sock == INVALID_SOCKET ) { return NULL; } buf = (char *)calloc( 1024 + 1, sizeof( char ) ); if ( buf ) { if ( GetSocketType() == MIKAN_SOCKET_TCP || from == NULL ) { // TCP while ( ( len = recv( sock, buf + head, 1024, 0 ) ) && nonblocking ) { // ノンブロッキングなら、データを全て受け取るまでデータを回せる。 head += len; buf = (char *)realloc( buf, 1024 + head + 1 ); } } else if ( GetSocketType() == MIKAN_SOCKET_UDP || from != NULL ) { // UDP while ( ( len = recvfrom( sock, buf + head, 1024, 0, from, &fromsize ) ) && nonblocking ) { // ノンブロッキングなら、データを全て受け取るまでデータを回せる。 head += len; buf = (char *)realloc( buf, 1024 + head + 1 ); } } else { // エラー } if ( len < 1 ) { if ( nonblocking && GetLastError() == WSAEWOULDBLOCK ) { // まだ来ない。 } else { //エラー } len = 0; } len += head; } //サイズを入れるint型ポインタが指定されているならサイズを代入する。 if ( getsize ) { *getsize = len; } loadsize += len; buf[ len ] = '\0'; //受け取ったデータの文字列を返す。 return buf; }