รับที่อยู่ IP ของไคลเอนต์ใน socket.io


133

เมื่อใช้ socket.IO ในเซิร์ฟเวอร์ Node.js มีวิธีง่ายๆในการรับที่อยู่ IP ของการเชื่อมต่อขาเข้าหรือไม่? ฉันรู้ว่าคุณสามารถรับได้จากการเชื่อมต่อ HTTP มาตรฐาน แต่ socket.io เป็นสัตว์ร้ายที่แตกต่างกันเล็กน้อย


3
สัมผัสเล็กน้อย แต่ console.cat (ซ็อกเก็ต) อาจช่วยได้โดยการทิ้งทุกอย่างซ้ำ ๆ ในวัตถุซ็อกเก็ตลงบนคอนโซล
izb

4
@izb จุดดี แต่console.dir(socket)อาจเป็นอย่างที่คุณหมายถึง
LanguagesNamedAfterCofee

คำตอบ:


160

โอเค ณ 0.7.7 มีให้ แต่ไม่ใช่ในลักษณะที่ lubar อธิบาย ฉันต้องแยกวิเคราะห์บันทึกการกระทำบน git hub เพื่อหาสิ่งนี้ แต่ตอนนี้รหัสต่อไปนี้ใช้งานได้จริงสำหรับฉัน:

var io = require('socket.io').listen(server);

io.sockets.on('connection', function (socket) {
  var address = socket.handshake.address;
  console.log('New connection from ' + address.address + ':' + address.port);
});

5
อืม ... เพราะเขาคือ. connection.remoteAddress และของฉันคือ .handshake.address?
Toji

2
@GarciadelCastillo คุณอยู่หลังพร็อกซี ลองสิ่งนี้: stackoverflow.com/a/11187053/971459
Samson

4
ไม่ทำงานใน v1.0 - เพียงแค่บันทึกที่อยู่ของโฮสต์ให้ฉัน
Iest

1
ตามเวอร์ชัน1.3.7นี้จะกลับมา::ffff:127.0.0.1
dmr07

3
socket.request.connection.remoteAddressสำหรับรุ่น 1.x
Lukas Liesis

73

สำหรับ 1.0.4:

io.sockets.on('connection', function (socket) {
  var socketId = socket.id;
  var clientIp = socket.request.connection.remoteAddress;

  console.log(clientIp);
});

คุณได้รับข้อมูลจากที่ไหน ฉันคิดว่าฉันได้อ่านเอกสารทั้งหมดสำหรับ socket.io แล้วและไม่เห็นสิ่งนี้ มันทำงานได้อย่างสมบูรณ์เพื่อแก้ปัญหาของฉันที่คล้ายกับ OP
MikeB

1
เพียงแค่ซ็อกเก็ต console.log เพื่อดูข้อมูลที่มีอยู่ทั้งหมดฉันเชื่อว่ามันเปลี่ยนแปลงไปเรื่อย ๆ เพราะไม่ได้บันทึก
Pez Cuckow

6
ใน v1.2.1 socket.request.connection.remoteAddressและsocket.request.connection.remotePortทำงานให้ฉัน อย่างไรก็ตามฉันไม่เห็นคุณสมบัติเหล่านี้ในรายการเมื่อฉันลอง: console.log(util.inspect(socket.request.connection, {showHidden: true, colors: true})); ทำไมไม่?
Jeffrey LeCours

1
ทำงานใน 1.3.4 ด้วย ขอบคุณ
lima_fil

3
ตามเวอร์ชัน1.3.7นี้จะกลับมา::ffff:127.0.0.1
dmr07

46

หากคุณใช้เซิร์ฟเวอร์อื่นเป็นพร็อกซีย้อนกลับฟิลด์ที่กล่าวถึงทั้งหมดจะมี localhost วิธีแก้ปัญหาที่ง่ายที่สุดคือการเพิ่มส่วนหัวสำหรับ ip / port ในพร็อกซีเซิร์ฟเวอร์

ตัวอย่างสำหรับ nginx: เพิ่มสิ่งนี้หลังจากของคุณproxy_pass:

proxy_set_header  X-Real-IP $remote_addr;
proxy_set_header  X-Real-Port $remote_port;

สิ่งนี้จะทำให้ส่วนหัวพร้อมใช้งานในเซิร์ฟเวอร์โหนด socket.io:

var ip = socket.handshake.headers["x-real-ip"];
var port = socket.handshake.headers["x-real-port"];

โปรดทราบว่าส่วนหัวจะถูกแปลงเป็นตัวพิมพ์เล็กภายใน

หากคุณกำลังเชื่อมต่อเซิร์ฟเวอร์โหนดโดยตรงกับไคลเอนต์

var ip = socket.conn.remoteAddress;

ทำงานร่วมกับ socket.io เวอร์ชัน 1.4.6 สำหรับฉัน


5
นี่เป็นทางออกที่ดีที่สุดคำตอบอื่น ๆ ใช้ไม่ได้หาก nodejs อยู่หลังพร็อกซี
Alfredo Gt

2
@zuim คุณชายเป็นฮีโร่ของฉัน!
Flavio

20

สำหรับเวอร์ชันล่าสุดของ socket.io ให้ใช้

socket.request.connection.remoteAddress

ตัวอย่างเช่น:

var socket = io.listen(server);
socket.on('connection', function (client) {
  var client_ip_address = socket.request.connection.remoteAddress;
}

ระวังว่าโค้ดด้านล่างส่งคืน IP ของเซิร์ฟเวอร์ไม่ใช่ IP ของลูกค้า

var address = socket.handshake.address;
console.log('New connection from ' + address.address + ':' + address.port);

2
ฉันกำลังจะลองใช้รหัสการจับมือขอบคุณที่ชี้ให้เห็นว่ามันไร้ประโยชน์ !!
RozzA

1
"เวอร์ชันล่าสุด socket.io" หมายถึงเวอร์ชันใด โปรดระบุเวอร์ชันที่เฉพาะเจาะจง
Akseli Palén

ล่าสุดสำหรับกรกฎาคม 2014
SlyBeaver

8

เมื่อใช้1.0.6เวอร์ชันล่าสุดSocket.IOและติดตั้งแอปของHerokuฉันฉันได้รับไคลเอนต์IPและportใช้headersในsocket handshake:

var socketio = require('socket.io').listen(server);

socketio.on('connection', function(socket) {

  var sHeaders = socket.handshake.headers;
  console.info('[%s:%s] CONNECT', sHeaders['x-forwarded-for'], sHeaders['x-forwarded-port']);

}

6

ตั้งแต่ socket.io 1.1.0 ฉันใช้:

io.on('connection', function (socket) {
  console.log('connection :', socket.request.connection._peername);
  // connection : { address: '192.168.1.86', family: 'IPv4', port: 52837 }
}

แก้ไข : โปรดทราบว่านี่ไม่ใช่ส่วนหนึ่งของ API อย่างเป็นทางการดังนั้นจึงไม่รับประกันว่าจะทำงานใน socket.io รุ่นต่อ ๆ ไป

โปรดดูลิงก์ที่เกี่ยวข้องนี้ด้วย: ปัญหา engine.io


1
ยืนยันด้วย 1.3.3 ด้วย
Codesleuth

@Rachael @ Codesleuth ขอบคุณสำหรับการยืนยันสำหรับเวอร์ชันนี้เป็นที่ชื่นชมมาก ฉันได้รับการโหวตเพิ่มขึ้นเล็กน้อยดังนั้นฉันคิดว่านี่ยังใช้ได้ แต่ฉันยังไม่ได้ทดสอบตัวเอง
nha

6

เวอร์ชัน 0.7.7 ของ Socket.IO อ้างว่าส่งคืนที่อยู่ IP ของไคลเอ็นต์แล้ว ฉันประสบความสำเร็จกับ:

var socket = io.listen(server);
socket.on('connection', function (client) {
  var ip_address = client.connection.remoteAddress;
}

2
client.conn.remoteAddress; ในเวอร์ชันที่ใหม่กว่า
Mujtaba Kably

4

ดูเหมือนว่าจะได้ผล:

var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
  var endpoint = socket.manager.handshaken[socket.id].address;
  console.log('Client connected from: ' + endpoint.address + ":" + endpoint.port);
});

1
สิ่งนี้จะคืนค่า127.0.0.1ให้ฉันเสมอไม่ใช่ IP ของไคลเอนต์ (node.js ทำงานบนเซิร์ฟเวอร์ระยะไกล)
Daniel W.

ลองใช้ socket.request.connection.remoteAddress
Lukas Liesis

โปรดระบุเวอร์ชัน Socket.io ที่คุณใช้อยู่
Akseli Palén

4

ฉันพบว่าภายใน socket.handshake.headers มีการส่งต่อสำหรับที่อยู่ซึ่งไม่ปรากฏในเครื่องของฉัน และฉันสามารถรับที่อยู่ระยะไกลโดยใช้:

socket.handshake.headers['x-forwarded-for']

นี่คือในฝั่งเซิร์ฟเวอร์ไม่ใช่ฝั่งไคลเอ็นต์


1
ทุกสิ่งทุกอย่างที่ฉันพยายามส่งคืน::ffff:127.0.0.1แต่สิ่งนี้ทำให้ฉันได้ IP จริง
Steven Pothoven

รักคุณ anwers อื่น ๆ ทั้งหมดให้ฉันย้อนกลับ ip ส่วนหัวนี้เท่านั้นที่ใช้งานได้!
datdinhquoc

นี่คือโซลูชันสำหรับเวอร์ชันล่าสุด [2.2.0] อย่างอื่นส่งคืนเซิร์ฟเวอร์ ip ให้ฉัน
Abdul Sadik Yalcin

3

จากการอ่านซอร์สโค้ด socket.io ดูเหมือนว่าเมธอด "listen" จะใช้อาร์กิวเมนต์ (เซิร์ฟเวอร์, ตัวเลือก, fn) และถ้า "เซิร์ฟเวอร์" เป็นอินสแตนซ์ของเซิร์ฟเวอร์ HTTP / S ก็จะรวมมันไว้ให้คุณ

ดังนั้นคุณจึงสามารถให้เซิร์ฟเวอร์ว่างซึ่งรับฟังเหตุการณ์ 'การเชื่อมต่อ' และจัดการกับที่อยู่ของซ็อกเก็ต remoteAddress อย่างไรก็ตามสิ่งต่างๆอาจยากมากหากคุณต้องการเชื่อมโยงแอดเดรสนั้นกับอ็อบเจ็กต์ socket.io Socket จริง

var http = require('http')
  , io = require('socket.io');
io.listen(new http.Server().on('connection', function(sock) {
  console.log('Client connected from: ' + sock.remoteAddress);
}).listen(80));

อาจจะง่ายกว่าในการส่งแพทช์ไปที่ socket.io โดยที่วัตถุ Socket ของตัวเองถูกขยายด้วยคุณสมบัติ remoteAddress ที่กำหนดในเวลาเชื่อมต่อ ...


แพทช์นี้น่าจะรวมอยู่ในรุ่นถัดไปgithub.com/LearnBoost/Socket.IO-node/pull/286
mak

3

ง่ายมาก. ใส่ครั้งแรก

io.sockets.on('connection', function (socket) {

console.log(socket);

คุณจะเห็นช่องทั้งหมดของซ็อกเก็ต จากนั้นใช้ CTRL + F และค้นหาที่อยู่ของคำ สุดท้ายเมื่อคุณพบฟิลด์ remoteAddress ใช้จุดเพื่อกรองข้อมูล ในกรณีของฉันมันคือ

console.log(socket.conn.remoteAddress);

วันนี้ฉันพบทางออกเดียวกันในเรื่องที่คล้ายกัน!
Filippo1980

สิ่งนี้ไม่ได้ให้ IP ของปลายทางไคลเอ็นต์ ในกรณีของฉันมันส่งคืน IP ของพร็อกซีเซิร์ฟเวอร์ย้อนกลับ
Akseli Palén

3

ใน socket.io 2.0 : คุณสามารถใช้:

socket.conn.transport.socket._socket.remoteAddress

ใช้งานได้กับ transports: ['websocket']


3

สิ่งนี้ใช้ได้กับเวอร์ชัน2.3.0ล่าสุด:

io.on('connection', socket => {
   const ip = socket.handshake.headers[x-forwarded-for] || socket.conn.remoteAddress.split(":")[3];
   console.log(ip);
});




1

เวอร์ชันล่าสุดใช้งานได้กับ:

console.log(socket.handshake.address);

5
ตามเวอร์ชัน1.3.7นี้จะกลับมา::ffff:127.0.0.1
dmr07

คล้าย 1.4.8 :: ffff: 10.0.0.7
Xin

1
@ dmr07 นี่คือเวอร์ชัน IPv6 คุณสามารถบังคับ IPv4 โดยการทำให้เซิร์ฟเวอร์ HTTP 0.0.0.0ฟัง ที่เกี่ยวข้อง: stackoverflow.com/a/37378670/5138796
darrachequesne

คุณสามารถทำ console.log (socket.handshake.address.substring (7)) มันจะพิมพ์ ip 127.0.0.1
node_man

1

ยินดีต้อนรับปี 2019 ที่ typescript เข้าครอบงำโลกอย่างช้าๆ คำตอบอื่น ๆ ยังคงใช้ได้อย่างสมบูรณ์ อย่างไรก็ตามฉันแค่อยากจะแสดงให้คุณเห็นว่าคุณสามารถตั้งค่านี้ในสภาพแวดล้อมที่พิมพ์ได้อย่างไร

ในกรณีที่คุณยังไม่ได้ทำ ครั้งแรกที่คุณควรติดตั้งการอ้างอิงบางอย่าง (เช่นจาก commandline นี้: npm install <dependency-goes-here> --save-dev)

  "devDependencies": {
    ...
    "@types/express": "^4.17.2",
    ...
    "@types/socket.io": "^2.1.4",
    "@types/socket.io-client": "^1.4.32",
    ...
    "ts-node": "^8.4.1",
    "typescript": "^3.6.4"
  }

ฉันกำหนดการนำเข้าโดยใช้การนำเข้า ES6 (ซึ่งคุณควรเปิดใช้งานในtsconfig.jsonไฟล์ของคุณก่อน)

import * as SocketIO from "socket.io";
import * as http from "http";
import * as https from "https";
import * as express from "express";

เนื่องจากฉันใช้ typescript ฉันจึงพิมพ์เต็มในทุกสิ่งที่ฉันทำกับวัตถุเหล่านี้

ดังนั้นก่อนอื่นคุณต้องมีเซิร์ฟเวอร์ http:

const handler = express();

const httpServer = (useHttps) ?
  https.createServer(serverOptions, handler) :
  http.createServer(handler);

ฉันเดาว่าคุณทำทั้งหมดนั้นแล้ว และคุณอาจเพิ่ม socket io ไปแล้ว:

const io = SocketIO(httpServer);
httpServer.listen(port, () => console.log("listening") );
io.on('connection', (socket) => onSocketIoConnection(socket));

ถัดไปสำหรับการจัดการการเชื่อมต่อ socket-io ใหม่คุณสามารถใส่SocketIO.Socketประเภทลงในพารามิเตอร์ได้

function onSocketIoConnection(socket: SocketIO.Socket) {      
  // I usually create a custom kind of session object here.
  // then I pass this session object to the onMessage and onDisconnect methods.

  socket.on('message', (msg) => onMessage(...));
  socket.once('disconnect', (reason) => onDisconnect(...));
}

และในที่สุดเนื่องจากตอนนี้เราพิมพ์เต็มแล้วเราจึงสามารถดึง ip จากซ็อกเก็ตของเราได้อย่างง่ายดายโดยไม่ต้องเดา:

const ip = socket.conn.remoteAddress;
console.log(`client ip: ${ip}`);

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.