Socket.IO - bağlı soketlerin / istemcilerin listesini nasıl edinebilirim?


159

Şu anda bağlı olan tüm soketlerin / istemcilerin bir listesini almaya çalışıyorum.

io.sockets maalesef bir dizi döndürmüyor.

Bir dizi kullanarak kendi listemi tutabileceğimi biliyorum, ancak bunun 2 nedenden dolayı en uygun çözüm olduğunu düşünmüyorum:

  1. Fazlalık. Socket.IO bu listenin bir kopyasını zaten tutar.

  2. Socket.IO, istemciler için rasgele alan değerleri ayarlamak için yöntem sağlar (yani:), socket.set('nickname', 'superman')bu yüzden kendi listemi korumak için bu değişiklikleri takip etmem gerekir.

Yardım?


Sadece io.sockets'i bir diziye dönüştüremez misiniz?
mak

2
0.7.6 io.sockets.sockets basit bir karma nesne id => soket
mak

1
Bunu fark ettim, ama garip davranıyor (standart soket nesneleri gibi görünmüyor). Örneğin denedim: pastebin.com/fxuzVckS ancak soket nesnesinin bir 'get' yöntemi içermediğini söylüyor.
Andy Hin

3
socketid, io.sockets.sockets[socket]yuva.
mak

2
İlk argüman errve bellek deposu kullanıyorsanız her zaman null. .get('nickname', function(err, nickname) { ... })
mak

Yanıtlar:


173

Socket.IO 0.7'de bir clients ad alanlarında yönteminiz , bu tüm bağlı soketlerin bir dizisini döndürür.

Ad alanı olmayan API:

var clients = io.sockets.clients();
var clients = io.sockets.clients('room'); // all users from room `room`

Bir ad alanı için

var clients = io.of('/chat').clients();
var clients = io.of('/chat').clients('room'); // all users from room `room`

Umarım bu gelecekte birine yardımcı olur

NOT: Bu Çözüm SADECE 1.0 sürümünden önceki sürümlerle çalışır


GÜNCELLEME 2020 Mar 06

1.x ve üstü için lütfen şu bağlantıya bakın: socket.io'daki bir sohbet odasında kaç kişinin bulunduğunu alma


3
Sanırım 1.0'da istemciler yöntemini düşürdüler ... sadece şu anda kontrol ediyorlar ...
marksyzm

7
Tam bir yeniden yazma olduğu için neredeyse her şeyi 1.0'da bıraktılar. Ama 1.0 yıllardır yayınlanmamış gibi. 1.0'da connectedad alanının nesnesini kullanmanız gerekir .
3rdEden

6
@ 3rdEden, bağlı ad alanının nesnesinin sözdizimi nedir? var clients = io.sockets.connected();Açıkçası çalışmıyor. Teşekkürler
Kaya Toast


TypeError: fn.bind bir işlev değil
Iman Marashi

101

Socket.io 1.4

Object.keys(io.sockets.sockets); bağlı tüm soketleri verir.

Socket.io 1.0 socket.io 1.0'dan itibaren, kabul edilen gerçek cevap artık geçerli değildir. Bu yüzden geçici bir düzeltme olarak kullandığım küçük bir işlev yaptım:

function findClientsSocket(roomId, namespace) {
    var res = []
    // the default namespace is "/"
    , ns = io.of(namespace ||"/");

    if (ns) {
        for (var id in ns.connected) {
            if(roomId) {
                var index = ns.connected[id].rooms.indexOf(roomId);
                if(index !== -1) {
                    res.push(ns.connected[id]);
                }
            } else {
                res.push(ns.connected[id]);
            }
        }
    }
    return res;
}

İçin Api yok ad olur

// var clients = io.sockets.clients();
// becomes : 
var clients = findClientsSocket();

// var clients = io.sockets.clients('room');
// all users from room `room`
// becomes
var clients = findClientsSocket('room');

Bir ad alanı için Api :

// var clients = io.of('/chat').clients();
// becomes
var clients = findClientsSocket(null, '/chat');

// var clients = io.of('/chat').clients('room');
// all users from room `room`
// becomes
var clients = findClientsSocket('room', '/chat');

Ayrıca belirli bir oda için soketleri döndüren bir işlev verdiğim bu ilgili soruya bakın .

function findClientsSocketByRoomId(roomId) {
var res = []
, room = io.sockets.adapter.rooms[roomId];
if (room) {
    for (var id in room) {
    res.push(io.sockets.adapter.nsp.connected[id]);
    }
}
return res;
}

Soket.io 0.7

Ad alanı olmayan API :

var clients = io.sockets.clients();
var clients = io.sockets.clients('room'); // all users from room `room`

İçin bir ad

var clients = io.of('/chat').clients();
var clients = io.of('/chat').clients('room'); // all users from room `room`

Not: socket.io API'sı kırılmaya eğilimli göründüğü ve bazı çözümlerin uygulama ayrıntılarına dayandığı için, müşterileri kendiniz izleme meselesi olabilir:

var clients = [];

io.sockets.on('connect', function(client) {
    clients.push(client); 

    client.on('disconnect', function() {
        clients.splice(clients.indexOf(client), 1);
    });
});

3
Bunun için teşekkür ederim. Bu işlevi çıkardıklarına şaşırdım.
Tyler Scott

1
@TylerScott Özellikle göçmen rehberlerinde yer almadığı göz önüne alındığında (bir şey eksik olmadıkça). socket.io/docs/migrating-from-0-9
nha

@nha, bu benim için işe yaramaz, ancak bir soket dizisi yerine 0, 1 ve 2 vb. gibi bir Tamsayı dizisi döndürür. Herhangi bir fikir?
ThePixelPony

birden fazla düğüm için ne dersin? çünkü redis mağazası ile birden fazla düğüm kullanıyorum
John Nguyen

3
@nha cevabınız tam olarak, ancak redis store sunucusu ile birden fazla düğüm için çalışmıyor. 1 düğüm işleminden, ns.connected [id] kullanarak bağlı soketi kontrol edemezsiniz
John Nguyen

46

Socket.io 1.0'dan sonra kullanamayız

io.sockets.clients(); 
or
io.sockets.clients('room'); 

Artık. Bunun yerine aşağıdakileri kullanabilirsiniz

var clients_in_the_room = io.sockets.adapter.rooms[roomId]; 
for (var clientId in clients_in_the_room ) {
  console.log('client: %s', clientId); //Seeing is believing 
  var client_socket = io.sockets.connected[clientId];//Do whatever you want with this
}

3
değiştiririmvar clients_in_the_room = io.sockets.adapter.rooms[roomId].sockets
Fábio Zangirolami

37

Socket.IO 1.x Kullanma:

Bağlı istemcilerin dizisini alın:

io.engine === io.eio // => true
Object.keys(io.engine.clients) // => [ 'US8AxrUrrDF_G7ZUAAAA', 'Ov2Ca24Olkhf2NHbAAAB' ]
Object.keys(io.eio.clients)    // => [ 'US8AxrUrrDF_G7ZUAAAA', 'Ov2Ca24Olkhf2NHbAAAB' ]

Bağlı istemci sayısını alın:

io.engine.clientsCount // => 2
io.eio.clientsCount    // => 2

32

Socket.io 1.3 içinde çok basit:

io.sockets.sockets- bağlı soket nesnelerini içeren bir dizidir. Kullanıcı adını her sokete kaydettiyseniz şunları yapabilirsiniz:

io.sockets.sockets.map(function(e) {
    return e.username;
})

Boom. Bağlı tüm kullanıcıların adlarına sahipsiniz.


2
Teşekkürler! Basitlik için +1. Bu yöntem ile diyelim ki Joseph Dykstra'nın cevabı arasında herhangi bir fark olup olmadığını biliyor musunuz? (Object.keys(io.engine.clients)
cyclingLinguist

4
Bu v1.4.5 üzerinde çalışmaz. Hala bir çözüm üzerinde çalışıyor
Nuno Furtado

buldun mu? \
ocram

2
TypeError: io.sockets.sockets.map bir işlev değil
Király István

23

Bugün bu acıyı yaşadım. API'leri için uygun bir dokümantasyon yapabilirlerse Socket.io çok daha iyi olacaktır.

Neyse, io.sockets içine bakmaya çalıştım ve kullanabileceğimiz bir dizi seçenek buldum:

io.sockets.connected //Return {socket_1_id: {}, socket_2_id: {}} . This is the most convenient one, since you can just refer to io.sockets.connected[id] then do common things like emit()
io.sockets.sockets //Returns [{socket_1}, {socket_2}, ....]. Can refer to socket_i.id to distinguish
io.sockets.adapter.sids //Return {socket_1_id: {}, socket_2_id: {}} . Looks similar to the first one but the object is not actually the socket, just the information.

// Not directly helps but still relevant
io.sockets.adapter.rooms //Returns {room_1_id: {}, room_2_id: {}}
io.sockets.server.eio.clients //Return client sockets
io.sockets.server.eio.clientsCount //Return number of connected clients

Ayrıca, socket.io öğesini ad alanı ile kullanırken, io.sockets bir nesne yerine bir dizi haline geldiğinden yukarıdaki yöntemlerin kırılacağını unutmayın. Çözmek için io.sockets yerine io yazın (yani io.sockets.connected io.connected olur, io.sockets.adapter.rooms io.adapter.rooms olur ...)

Socket.io üzerinde test edilmiştir 1.3.5


1
@ Зелёный Ad alanını kullanmıyorsanız çalışacaktır. Ad alanı kullanıyorsanız, io.server.eio.clientsCount
Thanh Nguyen olarak

2
Evet, resmi belgeler çok geliştirilebilir
CodeAndCats

19

Sürüm +2.0

+2.0 sürümünde sorguladığınız ad alanını / oda / düğümü belirtirsiniz.

Yayında olduğu gibi, varsayılan değer varsayılan ad alanından ('/') tüm istemcilerdir:

const io = require('socket.io')();  
io.clients((error, clients) => {
      if (error) throw error;
      console.log(clients); // => [6em3d4TJP8Et9EMNAAAA, G5p55dHhGgUnLUctAAAB]
});

Belirli bir ad alanına bağlı istemci kimlikleri listesini alır (varsa tüm düğümlerde).

const io = require('socket.io')();
io.of('/chat').clients((error, clients) => {
     if (error) throw error;
     console.log(clients); // => [PZDoMHjiu8PYfRiKAAAF, Anw2LatarvGVVXEIAAAD]
});

Ad alanının odasındaki tüm istemcileri almak için bir örnek:

const io = require('socket.io')();
io.of('/chat').in('general').clients((error, clients) => {
      if (error) throw error;
      console.log(clients); // => [Anw2LatarvGVVXEIAAAD] 
});

Bu resmi belgelerden alınmıştır: Socket.IO Server-API


1
tüm soket nesnelerini görüntülemenin bir yolu var mı? örneğin, socket.usernamebağlantıdaki her sokete bir özellik eklerseniz , bu soket nesnelerinin tümünü (her sokete eklediğim özel özellikler dahil) görüntüleyebilmemin bir yolu var mı? (referans olarak, şu anda bir istemci bağlandığında ek soket bilgilerini saklamak için genel bir nesne değişkeni kullanıyorum - bu yüzden nasıl ayarlanacağını sormuyorum - sadece tüm soket nesnelerini 'varsayılan' olarak görüntülemenin bir yolu olup olmadığını bilmekle ilgileniyorum) .
user1063287

1
hmm bu Yanıt başına , sana bağlı tüm prizler görebilirsiniz düşünüyorum console.log(io.sockets.connected)- her özellik değeri bu özellikleri içeren bir "yuva nesnesi" olan bir nesne gibi görünüyor nsp, server, adaptor, id(bir dize), client, conn, rooms, acks, connected, disconnected, handshake, fns, flags, _rooms, _events, _eventsCountve nihayet usernameben bağlantıda her sokete eklemek özel özellik olan.
user1063287

17

Soket nesnesine sunucudan erişebileceğimizi düşünüyorum ve takma adı atayabilir ve soket kimliğini gösterebilirsiniz,

io.sockets.on('connection',function(socket){ 
    io.sockets.sockets['nickname'] = socket.id;
    client.on("chat", function(data) {      
        var sock_id = io.sockets.sockets['nickname']
        io.sockets.sockets[sock_id].emit("private", "message");
    });    
});

Tarihinde disconnectlütfen takma adı kaldırın io.sockets.sockets.


'client.on' un amacı nedir? Kodunuzu şu şekilde kullanabilir misiniz (yalnızca 1 soketten veri kabul ediyor) ?: io.sockets.sockets [sock_id] .on ('newmessage', function (data) {console.log (data)});
Hawk

9

Bu, socket.io 1.3 adresinden erişmenin en iyi yoludur

Object.keys(socket.adapter.rooms[room_id])


lütfen bu örneği paylaşmama izin verin, var room = io.sockets.adapter.rooms[room_id]; var connections = _.map(Object.keys(room), function(socketId){ return (io.sockets.connected[socketId].connected == true) });
Hany Alsamman

5

Sadece bağlı istemcilerin bir COUNT isteyen herkes bunun yapacağına inanıyorum:

io.sockets.manager.server.connections


bağlı istemciler sayılmaz, test edilir. (biraz daha)
mrzmyr

5
doğru kullanım içinio.sockets.clients().length
Ivo

2
Şu ikisi io.sockets.manager.server.connectionsve io.sockets.clients().lengthdo not çalışması. Bu benim için çalıştı - Sadece saymak için - io.engine.clientsCountve müşteri listesi için - io.engine.clientsCount. 3 yıldır bu şekilde kaldığı için. Bağlantı bilgilerini almanın güvenilir bir yolu gibi görünüyor. (Joseph Dykstra'nın cevabına göre)
Aswin Ramakrishnan

5

Soket.io 1.4.4

Sizin için örnek kodu.

function get_clients_by_room(roomId, namespace) {
        io.of(namespace || "/").in(roomId).clients(function (error, clients) {
            if (error) { throw error; }
            console.log(clients[0]); // => [Anw2LatarvGVVXEIAAAD]
            console.log(io.sockets.sockets[clients[0]]); //socket detail
            return clients;
        });
    }

Sanırım birine bu kod bloğuna yardımcı olacak.


4

Soket.IO 1.4'te

Bağlı Tüm Kullanıcılar dizisini almak için:

var allConnectedClients = Object.keys(io.sockets.connected);// This will return the array of SockeId of all the connected clients

Tüm müşterilerin Sayımını almak için:

var clientsCount = io.engine.clientsCount ; // This will return the count of connected clients


3

Socket.io 1.5 itibariyle, amortismana uğramış gibi görünen ve valueOf ile değiştirilen indexOf değişikliğine dikkat edin

function findClientsSocket(roomId, namespace) {
    var res = [];
    var ns = io.of(namespace ||"/");    // the default namespace is "/"

    if (ns) {
        for (var id in ns.connected) {
            if (roomId) {
                //var index = ns.connected[id].rooms.indexOf(roomId) ;
                var index = ns.connected[id].rooms.valueOf(roomId) ; //Problem was here

                if(index !== -1) {
                    res.push(ns.connected[id]);
                }
            } else {
                res.push(ns.connected[id]);
            }
        }
    }
    return res.length;
}

Socket.io sürüm 2.0.3 için aşağıdaki kod çalışır:

function findClientsSocket(io, roomId, namespace) {
    var res = [],
        ns = io.of(namespace ||"/");    // the default namespace is "/"

    if (ns) {
        for (var id in ns.connected) {
            if(roomId) {
                // ns.connected[id].rooms is an object!
                var rooms = Object.values(ns.connected[id].rooms);  
                var index = rooms.indexOf(roomId);
                if(index !== -1) {
                    res.push(ns.connected[id]);
                }
            }
            else {
                res.push(ns.connected[id]);
            }
        }
    }
    return res;
}

beni ne kadar acı kurtardığınızı hayal edemezsiniz
nicholaswmin

ama socket.io sürümü henüz 1.5 değil! Şimdi 1.4.8
leszek.hanusz

@MoleIsKing Obrigado amigo!

2

socket.io 1.3 bunu 2 satırda başardım

var usersSocketIds = Object.keys(chat.adapter.rooms['room name']);
var usersAttending = _.map(usersSocketIds, function(socketClientId){ return chat.connected[socketClientId] })

2

Soket.io 1.7.3 (+):

işlevi getConnectedList ()
{
    izin ver = []
    
    için (istemci io.sockets.connected içinde olsun)
    {
        list.push (istemci)
    }
    
    dönüş listesi
}

console.log (getConnectedList ())

// ['yIfhb2tw7mxgrnF6AAAA', 'qABFaNDSYknCysbgAAAB'] döndürür


2

Sürüm 2.3 için bu işe yarar ve soketi de alacak, bana öyle geliyor ki soket bir süre kullandıktan sonra çok hızlı ve çok az okunabilir belgeler ile değişiyor.

ioSite.of('/').in(roomId).clients((error, clients) => {
    if (error) throw error;
    for (var i=0;i<clients.length;i++) {
        clientId=clients[i];
        console.log(clientId);

        // load the socket of your namespace
        var socket=ioSite.of('/').in(roomId).connected[clientId]
        console.log(socket.constructor.name);
        console.log(socket.id);
    }
});

yine de bu doğru gelmiyor, çünkü her zaman Io soketinde bu duyguyu hissediyorum


1
bir çöp kütüphanesi olduğunu düşünmeye başladım. tek şey doğru sorunsuz aksi takdirde bütün mimari bok olduğunu ve 1 sohbet uygulaması üzerinde 1 ötesine ölçeklendirmez veri (json, ikili, vs) birçok çeşit aktarır
Muhammed Umer

1

Buna soketin manager özelliğinden erişebileceğinize inanıyorum?

var handshaken = io.manager.handshaken;
var connected = io.manager.connected;
var open = io.manager.open;
var closed = io.manager.closed;

3rdEden'in cevabı benim için işe yaramadı çünkü dizi bağlantıyı kesen istemcileri döndüren sayılardan çıkan sorunlar var. Object.keys (io.manager.open) .length, tecrübelerimin en güvenilir sayımı oldu. io.of ('/ namespace') .name alanlarını kullanıyorsanız manager.open dosyasını açın.
Wes Johnson

1

Burada çok iyi yanıtlar görüyorum ve pek çok yerde oldukça kullanışlı ama ihtiyaç duyduğum kadar değil. İlgilenen bir istemcinin belirli bir kayıttaki değişiklikleri dinleyebileceği bir pubsub özelliği için yuva kullanıyorum.

Benim özel sorun aynı soket aynı odada birkaç kez katılıyor oldu. Bunun çözümü, soketin oda özelliği içinde odaya sahip olup olmadığını kontrol etmekti.

var room = myObj.id.toString();
if (socket.rooms.indexOf(room) === -1) {
    socket.join(room);
    socket.emit('subscribed', {to : room});
} else {
    console.log("Already in room");
}

Umarım bu birine yardımcı olur.


Ben istemci 'soket bağlantı üzerine odaya katılmak yaparsanız, bu' if 'deyimi önlemek mümkün olduğunu düşünüyorum.
Chayemor

MyObj nereden geliyor? Bu değere nasıl ulaştınız?
Michael Draper

@MikeDraper myObject, kanal olarak işlev gören bir veritabanındaki kayıttır. Bunun çözdüğü şey, veritabanında her değişiklik olduğunda tüm istemcilerinizin güncellenmesini istediğiniz durumdur, örneğin bir kullanıcı adını güncelleştirir ve tüm bağlı istemciler bir güncelleme alır. Bu yüzden benzersiz (BSON) göz önüne alındığında, bu örnek kimliği için bir oda oluşturun. Kullanım durumum için çok özel bir değer, bu yüzden herhangi bir karışıklığa neden olduysam özür dilerim. Yardıma ihtiyacınız olursa bana bildirin :)
Gus Ortiz

@JMR benim app doğası nedeniyle bir soket birden fazla abone oldu, bu yüzden bu kontrol eklemek zorunda kaldı.
Gus Ortiz

1

Ad alanları veya odalar kullanmıyorsanız, Socket.IO 1.0+ sürümünün en basit yolu budur.

io.nsps["/"].sockets.length

Bu, varsayılan ad alanına bakar ve kullanmaya gerek kalmadan soket dizisinin uzunluğunu belirler Object.keys()


1

1.5.1 sürümünden itibaren, bir ad alanındaki tüm yuvalara aşağıdakilerle erişebiliyorum:

var socket_ids = Object.keys(io.of('/namespace').sockets);
socket_ids.forEach(function(socket_id) {
    var socket = io.of('/namespace').sockets[socket_id];
    if (socket.connected) {
        // Do something...
    }
});

Nedense, yuva kimliklerini saklamak için dizi yerine düz bir nesne kullanıyorlar.


Bu işe yarıyor. İo.of ('') içindeki boş bir dize ad alanı olmadan çalışır.
Király István

@ KirályIstván Bir süredir buna bakmadım, ama bence of()bu durumda zincirleme çağrıyı tamamen kaldırabilirsiniz .
rppc

1

Küme modu için redis bağdaştırıcısını kullanma

io.in(<room>).clients(function(err, clients) {

});

Her soketin kendisi bir oda olduğundan, aynı soketi kullanarak bir soketin var olup olmadığını bulabilir.


0

ES6 üreteçlerini kullanarak bir ad alanından bağlı soketlerin karmasını bir diziye dönüştürmenin hızlı bir yolu vardır (socket.io> = v1.0.0 için geçerlidir):

io.on('connection', function(socket) {
  var hash = io.of('/').connected
  var list = null

  hash[Symbol.iterator] = function*() {
    // for..of loop to invoke Object.keys() default iterator
    // to get the array values instead of the keys
    for(var id of Object.keys(hash)) yield hash[id]
  }

  list = [...hash]
  console.log(Array.isArray(list)) // true
})

0

Bunun hala devam edip etmediğini bilmiyorum. Ama böyle bir şey kullanarak sona erdi (Ben bağlı her soket üzerinde bir oturum nesnesi tutmak , sırayla kullanıcı adı ve diğer bilgileri içerir:

var connectedUsers = Object.keys(io.sockets.connected).map(function(socketId) {
    return io.sockets.connected[socketId].session.username;
});

0

Projede bir socket.io kümesi varsa, bu socket.io-redis adaptörünün kullanıldığı anlamına gelir .

Yukarıdaki gibi bir durum söz konusuysa, tüm bağlı soketlerin kimlik işlemlerinin alınması socket.io-redis adaptörüyle uygulanmalıdır. Aşağıdaki örnekler bunun için kullanılabilir;

io.of('/').adapter.clients(function (err, clients) {
  console.log("clients: ", clients); // an array containing all connected socket ids
});


io.of('/').adapter.allRooms(function (err, rooms) {
  console.log("all rooms: ", rooms);
});

Daha fazla bilgi için lütfen socket.io-redis github sayfasını ziyaret edin .


0

socket.io@1.7.3

Soket dizisini bağlı almak için Object.Keys kullandım. Daha sonra aynı dizi içinde yeni bir nesne dizisi oluşturmak için map fonksiyonu ile tekrarlayın

var connectedUsers = Object.keys(io.sockets.connected).map(function(socketId) {
    return { socket_id : socketId, socket_username: io.sockets.connected[socketId].username };
});

// test
console.log(connectedUsers);

Belki de bu cevap soket kimliği / kullanıcı adı dizisini almanıza yardımcı olabilir.


1
Merhaba - lütfen bunun sorunu nasıl çözdüğünü İngilizce olarak açıklayabilir misiniz? Bu şekilde sadece kodla ilgili bir cevap olmayacaktır. Teşekkürler!
Max von Hippel

0

v.10

var clients = io.nsps['/'].adapter.rooms['vse'];
/* 
'clients' will return something like:
Room {
sockets: { '3kiMNO8xwKMOtj3zAAAC': true, FUgvilj2VoJWB196AAAD: true },
length: 2 }
*/
var count = clients.length;  // 2
var sockets = clients.map((item)=>{  // all sockets room 'vse'
       return io.sockets.sockets[item];
      });
sample >>>
var handshake  = sockets[i].handshake; 
handshake.address  .time .issued ... etc.

1
Neden 'En iyi yol budur' cevabını ve cevabınızın yukarıdaki birçok cevaba nasıl bir şey eklediğini bilmek iyi olur. Kod bir şeydir, ancak bir cevabın da bir açıklaması olmalı. Gördüğünüz gibi, bu sorunun başka cevapları da var. Cevabınız konuya daha fazla bir şey getirmelidir, aksi takdirde gereksizdir.
Nathan Ripert

İle socket.io 2.1.1 olsun TypeError: clients.map is not a functionve umut verici görünüyor olsa da, yukarıdaki örneğin ne elde edeceğinden tamamen emin değilim - otomatik olarak kullanıcı adları dahil bir dizi istemci nesnesi oluşturacağını umuyordum :).
user1063287
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.