ใน C # จะตรวจสอบได้อย่างไรว่ามีพอร์ต TCP หรือไม่?


120

ใน C # เพื่อใช้ TcpClient หรือโดยทั่วไปเพื่อเชื่อมต่อกับซ็อกเก็ตฉันจะตรวจสอบก่อนว่าพอร์ตบางพอร์ตว่างบนเครื่องของฉันได้อย่างไร?

ข้อมูลเพิ่มเติม: นี่คือรหัสที่ฉันใช้:

TcpClient c;
//I want to check here if port is free.
c = new TcpClient(ip, port);

2
คำว่า "ฟรี" ที่นี่หมายความว่าอย่างไร หากคุณพยายามเชื่อมต่อแล้วล้มเหลวนั่นอาจหมายความว่าไม่มีอะไรรับฟัง
Jon Skeet

2
ฉันหมายความว่าไม่มีการใช้งานโดยแอปพลิเคชันอื่นใด หากแอปพลิเคชันใช้พอร์ตอื่นจะไม่สามารถใช้งานได้จนกว่าจะว่าง
อาลี

เซิร์ฟเวอร์ที่คุณพยายามเชื่อมต่อคืออะไร คุณเขียนมันหรือเป็นเซิร์ฟเวอร์ที่มีอยู่?
เสียใจ

3
ดังที่ได้ระบุไว้ในหลาย ๆ คำตอบคุณมีทุกอย่างย้อนหลัง พอร์ตภายในและพอร์ตระยะไกลเป็นสองสิ่งที่แตกต่างกันโดยสิ้นเชิง โดยเฉพาะคำตอบนี้อธิบายได้ดี: stackoverflow.com/questions/570098/…
bzlm

คำตอบ:


218

เนื่องจากคุณใช้ a TcpClientนั่นหมายความว่าคุณกำลังตรวจสอบพอร์ต TCP ที่เปิดอยู่ มีวัตถุดีๆมากมายในเนมสเปซSystem.Net.NetworkInformation

ใช้IPGlobalPropertiesวัตถุเพื่อไปยังอาร์เรย์ของTcpConnectionInformationวัตถุซึ่งคุณสามารถสอบถามเกี่ยวกับ IP ปลายทางและพอร์ตได้


 int port = 456; //<--- This is your value
 bool isAvailable = true;

 // Evaluate current system tcp connections. This is the same information provided
 // by the netstat command line application, just in .Net strongly-typed object
 // form.  We will look through the list, and if our port we would like to use
 // in our TcpClient is occupied, we will set isAvailable to false.
 IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
 TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();

 foreach (TcpConnectionInformation tcpi in tcpConnInfoArray)
 {
   if (tcpi.LocalEndPoint.Port==port)
   {
     isAvailable = false;
     break;
   }
 }

 // At this point, if isAvailable is true, we can proceed accordingly.

38
โปรดทราบว่ากระบวนการอื่นอาจเชื่อมโยงกับพอร์ตนั้นในขณะที่คุณกำลังตรวจสอบ
Serguei

2
สิ่งนี้เกี่ยวข้องกับคำถามอย่างไร คำตอบนี้เกี่ยวข้องกับพอร์ตท้องถิ่นไม่ใช่พอร์ตระยะไกล
bzlm

6
มีความเกี่ยวข้องในการตอบสนองคำขอของ OP ความแตกต่างในพื้นที่ / ระยะไกลแม้ว่า (เห็นด้วยกับคุณโดยสิ้นเชิง) ข้อกำหนดของ OP คือการสร้าง TcpClient ใหม่ด้วยพอร์ตที่ "ฟรี"
ก.ค.

8
โปรดทราบว่ารหัสนี้ตรวจสอบเฉพาะการเชื่อมต่อที่ใช้งานอยู่ การเชื่อมต่อที่ไม่มีการส่งหรือรับแพ็กเก็ตจะไม่ปรากฏในรายการ
JoeBilly

29
netstat -a -bเปรียบเทียบผลของรหัสดังกล่าวไปที่ โปรดสังเกตว่าไม่มีLISTENINGการเชื่อมต่อในไฟล์GetActiveTcpConnections(). คุณควรเช็คอินที่System.Net.IPEndPoints[]ส่งคืนภายในipGlobalProperties.GetActiveTcpListeners();
Mike de Klerk

44

คุณอยู่ผิดจุดสิ้นสุดของ Intertube เป็นเซิร์ฟเวอร์ที่สามารถเปิดได้เพียงพอร์ตเดียวเท่านั้น รหัสบางส่วน:

  IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
  try {
    TcpListener tcpListener = new TcpListener(ipAddress, 666);
    tcpListener.Start();
  }
  catch (SocketException ex) {
    MessageBox.Show(ex.Message, "kaboom");
  }

ล้มเหลวด้วย:

โดยปกติอนุญาตให้ใช้ที่อยู่ซ็อกเก็ตแต่ละอันเท่านั้น (โปรโตคอล / ที่อยู่เครือข่าย / พอร์ต) เท่านั้น


นั่นคือที่ที่ฉันจะไปด้วย มีคนสับสนที่นี่และเป็นไปได้ว่าฉัน
Moose

3
เป็นไปได้ว่าไคลเอนต์ต้องการพอร์ตบางพอร์ตเช่นกัน แต่ไม่ใช่เรื่องธรรมดา
Dave Van den Eynde

@DaveVandenEynde ที่จะเกิดขึ้นได้ก็ต่อเมื่อ "ไคลเอนต์" "ให้บริการ" บางอย่างบนพอร์ตนั้น ๆ (ทำให้เป็น "เซิร์ฟเวอร์" เป็นอย่างน้อยสำหรับพอร์ตนั้นเท่าที่เกี่ยวข้องกับ TCP) - เมื่อคุณมีการเชื่อมต่อ TCP ไคลเอ็นต์คุณจะไม่สามารถควบคุมพอร์ตขาออกได้ สแต็ก TCP กำหนดพอร์ตขาออกให้คุณและคุณไม่มีการควบคุมใด ๆ
BrainSlugs83

1
@ BrainSlugs83 คุณสามารถ: stackoverflow.com/questions/2869840/…
Dave Van den Eynde

นี่เป็นรหัสบิตที่ถูกต้องเพื่อตรวจสอบว่าพอร์ตว่างหรือไม่ อย่าลืมหยุด () TcpListener ในกรณีที่ทำสำเร็จ (เว้นแต่คุณตั้งใจจะใช้วัตถุ TcpListener เดียวกันเพื่อเริ่มฟังบนพอร์ต)
bgh

19

เมื่อคุณตั้งค่าการเชื่อมต่อ TCP 4-tuple (source-ip, source-port, dest-ip, dest-port) จะต้องไม่ซ้ำกัน - เพื่อให้แน่ใจว่าแพ็กเก็ตจะถูกส่งไปยังตำแหน่งที่ถูกต้อง

มีข้อ จำกัด เพิ่มเติมในฝั่งเซิร์ฟเวอร์ที่มีเพียงโปรแกรมเซิร์ฟเวอร์เดียวเท่านั้นที่สามารถผูกกับหมายเลขพอร์ตขาเข้าได้ (สมมติว่ามีที่อยู่ IP เดียวเซิร์ฟเวอร์หลาย NIC มีอำนาจอื่น ๆ แต่เราไม่จำเป็นต้องพูดถึงที่นี่)

ดังนั้นในตอนท้ายของเซิร์ฟเวอร์คุณ:

  • สร้างซ็อกเก็ต
  • ผูกซ็อกเก็ตนั้นเข้ากับพอร์ต
  • ฟังพอร์ตนั้น
  • ยอมรับการเชื่อมต่อบนพอร์ตนั้น และอาจมีการเชื่อมต่อหลายรายการเข้ามา (หนึ่งรายการต่อไคลเอนต์)

ในตอนท้ายของไคลเอนต์มักจะง่ายกว่าเล็กน้อย:

  • สร้างซ็อกเก็ต
  • เปิดการเชื่อมต่อ เมื่อลูกค้าเปิดการเชื่อมต่อที่จะระบุที่อยู่ IP และพอร์ตของเซิร์ฟเวอร์ มันสามารถระบุแหล่งที่มาของพอร์ต แต่มักจะใช้เป็นศูนย์ซึ่งผลในระบบกำหนดพอร์ตฟรีโดยอัตโนมัติ

นอกจากนี้ไม่มีความต้องการที่ปลายทาง IP / พอร์ตจะไม่ซ้ำกันเนื่องจากว่าจะส่งผลให้เพียงคนเดียวในช่วงเวลาที่ความสามารถในการใช้ Google และที่สวยดีจะทำลายรูปแบบธุรกิจของพวกเขา

ซึ่งหมายความว่าคุณสามารถทำสิ่งมหัศจรรย์เช่น FTP แบบหลายเซสชันได้เนื่องจากคุณตั้งค่าหลายเซสชันซึ่งความแตกต่างเพียงอย่างเดียวคือพอร์ตต้นทางของคุณทำให้คุณสามารถดาวน์โหลดชิ้นส่วนแบบขนานได้ Torrents มีความแตกต่างกันเล็กน้อยโดยที่ปลายทางของแต่ละเซสชันมักจะแตกต่างกัน

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


15
TcpClient c;

//I want to check here if port is free.
c = new TcpClient(ip, port);

... ฉันจะตรวจสอบก่อนว่าพอร์ตบางพอร์ตว่างบนเครื่องของฉันได้อย่างไร?

ฉันหมายความว่าไม่มีการใช้งานโดยแอปพลิเคชันอื่นใด หากแอปพลิเคชันใช้พอร์ตอื่นจะไม่สามารถใช้งานได้จนกว่าจะว่าง - อาลี

คุณเข้าใจผิดว่าเกิดอะไรขึ้นที่นี่

พารามิเตอร์ TcpClient (... ) เป็นของเซิร์ฟเวอร์ ip และพอร์ตเซิร์ฟเวอร์ที่คุณต้องการเชื่อมต่อ

TcpClient เลือกพอร์ตโลคัลชั่วคราวจากพูลที่พร้อมใช้งานเพื่อสื่อสารกับเซิร์ฟเวอร์ ไม่จำเป็นต้องตรวจสอบความพร้อมใช้งานของพอร์ตโลคัลเนื่องจากมีการจัดการโดยเลเยอร์ Winsock โดยอัตโนมัติ

ในกรณีที่คุณไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์โดยใช้ส่วนของโค้ดด้านบนปัญหาอาจเกิดจากหลายอย่าง (เช่นเซิร์ฟเวอร์ ip และ / หรือพอร์ตผิดเซิร์ฟเวอร์ระยะไกลไม่พร้อมใช้งาน ฯลฯ .. )


15

ขอบคุณสำหรับเคล็ดลับนี้ ฉันต้องการฟังก์ชันเดียวกัน แต่ในฝั่งเซิร์ฟเวอร์เพื่อตรวจสอบว่ามีการใช้พอร์ตหรือไม่ดังนั้นฉันจึงแก้ไขเป็นรหัสนี้

 private bool CheckAvailableServerPort(int port) {
    LOG.InfoFormat("Checking Port {0}", port);
    bool isAvailable = true;

    // Evaluate current system tcp connections. This is the same information provided
    // by the netstat command line application, just in .Net strongly-typed object
    // form.  We will look through the list, and if our port we would like to use
    // in our TcpClient is occupied, we will set isAvailable to false.
    IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
    IPEndPoint[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpListeners();

    foreach (IPEndPoint endpoint in tcpConnInfoArray) {
        if (endpoint.Port == port) {
            isAvailable = false;
            break;
        }
    }

    LOG.InfoFormat("Port {0} available = {1}", port, isAvailable);

    return isAvailable;
}

คุณไม่ต้องการสิ่งนี้ เพียงระบุพอร์ตศูนย์
Marquis of Lorne

หมายเหตุในความคิดเห็นของซอร์สโค้ด: "นี่เป็นข้อมูลเดียวกับที่แอปพลิเคชันบรรทัดคำสั่ง netstat ให้มา" - เป็นเรื่องโกหก มันไม่ได้ให้ข้อมูลเช่นเดียวกับคำสั่ง netstat ยังจัดเตรียม PID ของแอ็พพลิเคชันโดยใช้พอร์ต ( -anb) และไม่มีพารามิเตอร์ใด ๆ จะแสดงการเชื่อมต่อต่างประเทศเช่นเดียวกับสถานะ
Kraang Prime

6

ขอบคุณสำหรับคำตอบ jro ฉันต้องปรับแต่งสำหรับการใช้งานของฉัน ฉันต้องการตรวจสอบว่ามีการรับฟังพอร์ตหรือไม่และไม่จำเป็นต้องเปิดใช้งาน สำหรับสิ่งนี้ฉันแทนที่

TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();

กับ

IPEndPoint[] objEndPoints = ipGlobalProperties.GetActiveTcpListeners();.  

ฉันทำซ้ำอาร์เรย์ของปลายทางเพื่อตรวจสอบว่าไม่พบค่าพอร์ตของฉัน


แค่ลองฟังด้วยตัวคุณเอง คุณไม่จำเป็นต้องมีสิ่งนี้
Marquis of Lorne

5
string hostname = "localhost";
int portno = 9081;
IPAddress ipa = (IPAddress) Dns.GetHostAddresses(hostname)[0];


try
{
    System.Net.Sockets.Socket sock = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
    sock.Connect(ipa, portno);
    if (sock.Connected == true)  // Port is in use and connection is successful
            MessageBox.Show("Port is Closed");
    sock.Close();

}
catch (System.Net.Sockets.SocketException ex)
{
    if (ex.ErrorCode == 10061)  // Port is unused and could not establish connection 
        MessageBox.Show("Port is Open!");
    else
        MessageBox.Show(ex.Message);
}

ฉันเป็นคนหนึ่งที่พยายามเชื่อมต่อกับซ็อกเก็ต ฉันได้แก้ไขคำถามเพื่อให้ชัดเจนยิ่งขึ้น
อาลี

ฉันชอบรหัสนี้มากที่สุดซึ่งจะเปิดการเชื่อมต่อ TCP กับซ็อกเก็ตเพื่อดูว่ามีใครฟังอยู่อีกด้านหนึ่งหรือไม่ และฉันคิดว่าหลายคนต้องการสิ่งนี้จริง ๆ เมื่อต้องการ "ทดสอบว่าพอร์ตเปิดอยู่บนโฮสต์ระยะไกล" หรือไม่ อย่างไรก็ตามมีข้อผิดพลาดในโค้ดด้านบน: ถ้า (sock.Connected == true) แสดงว่าพอร์ตเปิดสำหรับการเชื่อมต่อซอฟต์แวร์ที่คล้ายเซิร์ฟเวอร์บางตัวกำลังฟังอยู่ หากมี SocketException ที่มี ErrorCode 10061 (ข้อความ "(0x80004005): ไม่สามารถทำการเชื่อมต่อได้เนื่องจากเครื่องเป้าหมายปฏิเสธอย่างแข็งขัน" แสดงว่าพอร์ตจะปิด!
Csaba Toth

มันก็เป็นอีกทางหนึ่งในข้อมูลโค้ด หมายเหตุอีกประการหนึ่ง: หากมีคนลองใช้ Dns.GetHostEntry ในการตั้งค่าการทดสอบดังกล่าวซึ่งคุณมีเซิร์ฟเวอร์เสมือนที่มีที่อยู่ IP เท่านั้นคุณจะมีข้อยกเว้น
Csaba Toth

3

netstat! นั่นคือยูทิลิตี้บรรทัดคำสั่งเครือข่ายที่มาพร้อมกับ windows จะแสดงการเชื่อมต่อที่สร้างขึ้นในปัจจุบันทั้งหมดและพอร์ตทั้งหมดที่กำลังรับฟังอยู่ คุณสามารถใช้โปรแกรมนี้เพื่อตรวจสอบได้ แต่ถ้าคุณต้องการทำสิ่งนี้จากการดูโค้ดในเนมสเปซ System.Net.NetworkInformation? เป็นเนมสเปซใหม่ตั้งแต่ 2.0 มีสินค้ามากมายที่นั่น แต่ในที่สุดถ้าคุณต้องการรับข้อมูลประเภทเดียวกันที่มีอยู่ผ่านคำสั่ง netstat คุณจะต้องส่งผลให้ P / Invoke ...

อัปเดต: System.Net.NetworkInformation

เนมสเปซนั้นมีคลาสมากมายที่คุณสามารถใช้เพื่อค้นหาสิ่งต่างๆเกี่ยวกับเครือข่าย

ฉันไม่พบรหัสเก่า ๆ นั้น แต่ฉันคิดว่าคุณสามารถเขียนสิ่งที่คล้ายกันได้ด้วยตัวเอง เริ่มต้นที่ดีคือการตรวจสอบIP Helper API Google MSDN สำหรับ ฟังก์ชันGetTcpTable WINAPI และใช้ P / Invoke เพื่อแจกแจงจนกว่าคุณจะมีข้อมูลที่ต้องการ


ฉันใช้. NET 3.5 และไม่สามารถปรับได้
อาลี

ให้ฉันปรับให้คุณ: msdn.microsoft.com/en-us/library/…
bzlm

3

ถ้าฉันไม่เข้าใจผิดมากนักคุณสามารถใช้ System.Network.w ก็ได้เพื่อตรวจสอบ

อย่างไรก็ตามสิ่งนี้จะเกิดขึ้นกับสภาพการแข่งขันเสมอ

วิธีการตรวจสอบมาตรฐานคือลองฟังจากพอร์ตนั้น หากคุณได้รับข้อผิดพลาดว่าพอร์ตไม่เปิด

ฉันคิดว่านี่เป็นส่วนหนึ่งของสาเหตุที่ bind () และ listen () เป็นการเรียกระบบสองสายที่แยกจากกัน


2

คุณพูด

ฉันหมายความว่าไม่ได้ใช้งานโดยแอปพลิเคชันอื่นใด หากแอปพลิเคชันใช้พอร์ตอื่นจะไม่สามารถใช้งานได้จนกว่าจะว่าง

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

ถ้าคุณ

   c = new TcpClient(ip, port);

ล้มเหลวแล้วไม่มีอะไรฟังที่นั่น มิฉะนั้นจะเชื่อมต่อแม้ว่าเครื่อง / แอปพลิเคชันอื่น ๆ จะมีซ็อกเก็ตที่เปิดไปยัง ip และพอร์ตนั้น


หากแอปพลิเคชันของฉันพยายามเชื่อมต่อโดยใช้พอร์ต 10 และอินสแตนซ์อื่นของแอปพลิเคชันของฉันพยายามเชื่อมต่อโดยใช้พอร์ต 10 อีกครั้งจะล้มเหลวเนื่องจากแอปพลิเคชันทั้งสองไม่สามารถส่งข้อมูลโดยใช้พอร์ตเดียวเมื่อต้องรับข้อมูลเช่นพอร์ต 80 ที่แตกต่างกัน
Ali

มันแตกต่างกันอย่างไร? ฟังพอร์ต 10 สำหรับแอปพลิเคชันของคุณคืออะไร
Moose

หากล้มเหลวเมื่ออินสแตนซ์ที่สองพยายามเชื่อมต่อแสดงว่าเป็นแอปพลิเคชันสำหรับการฟังไม่ใช่แอปพลิเคชันของคุณ
Moose

2

ipGlobalProperties.GetActiveTcpConnections() ไม่ส่งคืนการเชื่อมต่อใน Listen State

สามารถใช้พอร์ตสำหรับการฟังได้ แต่ไม่มีใครเชื่อมต่อกับมันวิธีการที่อธิบายไว้ข้างต้นจะไม่ได้ผล


วิธีใดที่อธิบายไว้ข้างต้น สิ่งนี้ตอบคำถามได้อย่างไร?
Marquis of Lorne

2

จากพอร์ตที่พร้อมใช้งานฉันจะไม่รวม:

  • การเชื่อมต่อ TCP ที่ใช้งานอยู่
  • ตัวฟัง TCP ที่ใช้งานอยู่
  • ผู้ฟัง UDP ที่ใช้งานอยู่

ด้วยการนำเข้าต่อไปนี้:

using System.Net.NetworkInformation;

คุณสามารถใช้ฟังก์ชันต่อไปนี้เพื่อตรวจสอบว่าพอร์ตสามารถใช้ได้หรือไม่:

private bool isPortAvalaible(int myPort)
{
    var avalaiblePorts = new List<int>();
    var properties = IPGlobalProperties.GetIPGlobalProperties();

    // Active connections
    var connections = properties.GetActiveTcpConnections();
    avalaiblePorts.AddRange(connections);

    // Active tcp listners
    var endPointsTcp = properties.GetActiveTcpListeners();
    avalaiblePorts.AddRange(endPointsTcp);

    // Active udp listeners
    var endPointsUdp = properties.GetActiveUdpListeners();
    avalaiblePorts.AddRange(endPointsUdp);

    foreach (int p in avalaiblePorts){
        if (p == myPort) return false;
    }
    return true;
}

ฉันให้ฟังก์ชันที่คล้ายกันสำหรับผู้ที่ใช้VB.NET :

Imports System.Net.NetworkInformation
Private Function isPortAvalaible(ByVal myPort As Integer) As Boolean
  Dim props As IPGlobalProperties = IPGlobalProperties.GetIPGlobalProperties()

  ' ignore active connections
  Dim tcpConnInfoArray() As TcpConnectionInformation = props.GetActiveTcpConnections()
  For Each tcpi As Net.NetworkInformation.TcpConnectionInformation In tcpConnInfoArray
    If tcpi.LocalEndPoint.Port = myPort Then
      Return False
    End If
  Next tcpi

  ' ignore active TCP listeners
  Dim activeTcpListeners() As Net.IPEndPoint = props.GetActiveTcpListeners
  For Each tcpListener As Net.IPEndPoint In activeTcpListeners
    If tcpListener.Port = myPort Then
      Return False
    End If
  Next tcpListener

  ' ignore active UPD listeners
  Dim activeUdpListeners() As Net.IPEndPoint = props.GetActiveUdpListeners
  For Each udpListener As Net.IPEndPoint In activeUdpListeners
    If udpListener.Port = myPort Then
      Return False
    End If
  Next udpListener

  Return True
End Function

2

เพื่อตอบคำถามที่แน่นอนในการค้นหาพอร์ตฟรี (ซึ่งเป็นสิ่งที่ฉันต้องการในการทดสอบหน่วยของฉัน) ใน dotnet core 3.1 ฉันได้สร้างสิ่งนี้ขึ้นมา

public static int GetAvailablePort(IPAddress ip) {
        TcpListener l = new TcpListener(ip, 0);
        l.Start();
        int port = ((IPEndPoint)l.LocalEndpoint).Port;
        l.Stop();
        Log.Info($"Available port found: {port}");
        return port;
    }

หมายเหตุ: ตามความคิดเห็นโดย @ user207421 เกี่ยวกับพอร์ตศูนย์ฉันค้นหาและพบสิ่งนี้และแก้ไขเล็กน้อย


1

โปรดทราบหน้าต่างเวลาระหว่างที่คุณทำการตรวจสอบและขณะที่คุณพยายามที่จะทำให้การเชื่อมต่อกระบวนการบางอย่างอาจใช้พอร์ต - คลาสสิกTOCTOU ทำไมคุณไม่ลองเชื่อมต่อดูล่ะ? หากล้มเหลวแสดงว่าคุณทราบว่าไม่มีพอร์ต


4
TOCTOU คือ YALAIHHOBIKTPBI (ยังเป็นคำย่ออีกยาวที่ฉันไม่เคยได้ยิน แต่ฉันรู้ว่าปรากฏการณ์เบื้องหลังมัน)
Csaba Toth

1

คุณไม่จำเป็นต้องรู้ว่าพอร์ตใดที่เปิดอยู่ในเครื่องของคุณเพื่อเชื่อมต่อกับบริการ TCP ระยะไกลบางอย่าง (เว้นแต่คุณต้องการใช้พอร์ตโลคัลเฉพาะ แต่โดยปกติจะไม่เป็นเช่นนั้น)

ทุกการเชื่อมต่อ TCP / IP จะระบุด้วยค่า 4 ค่า ได้แก่ IP ระยะไกลหมายเลขพอร์ตระยะไกล IP ในเครื่องหมายเลขพอร์ตภายในเครื่อง แต่คุณจำเป็นต้องทราบเฉพาะ IP ระยะไกลและหมายเลขพอร์ตระยะไกลเพื่อสร้างการเชื่อมต่อ

เมื่อคุณสร้างการเชื่อมต่อ tcp โดยใช้

TcpClient c;
c = TcpClient ใหม่ (remote_ip, remote_port);

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


นั่นเป็นสิ่งที่ดีสำหรับการตรวจสอบชุดซ็อกเก็ตที่กำหนด คำถามคือเกี่ยวกับซ็อกเก็ตเดียว (ซึ่งหมายเลขพอร์ตอาจไม่ระบุแม้ว่า (?))
Csaba Toth

1
    public static bool TestOpenPort(int Port)
    {
        var tcpListener = default(TcpListener);

        try
        {
            var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];

            tcpListener = new TcpListener(ipAddress, Port);
            tcpListener.Start();

            return true;
        }
        catch (SocketException)
        {
        }
        finally
        {
            if (tcpListener != null)
                tcpListener.Stop();
        }

        return false;
    }

0
test_connection("ip", port);


public void test_connection(String hostname, int portno) {
  IPAddress ipa = (IPAddress)Dns.GetHostAddresses(hostname)[0];
  try {
    System.Net.Sockets.Socket sock = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
   sock.Connect(ipa, portno);
   if (sock.Connected == true) {
     MessageBox.Show("Port is in use");
   }

   sock.Close();
 }
 catch (System.Net.Sockets.SocketException ex) {
   if (ex.ErrorCode == 10060) {
     MessageBox.Show("No connection.");
   }
 }
}

1
เมื่อโพสต์โค้ดบางส่วนให้พยายามอธิบายอย่างละเอียดว่าเหตุใดจึงเป็นวิธีแก้ปัญหา เพียงแค่รหัสอาจมีข้อมูลน้อยเกินไปและคำตอบของคุณมีความเสี่ยงที่จะถูกตรวจสอบ
Glubus

0

ตรวจสอบรหัสข้อผิดพลาด 10048

try
{
    TcpListener tcpListener = new TcpListener(ipAddress, portNumber);
    tcpListener.Start();
}
catch(SocketException ex)
{
    if(ex.ErrorCode == 10048)
    {
        MessageBox.Show("Port " + portNumber + " is currently in use.");
    }
    return;
}

-2

ลองทำเช่นนี้ในกรณีของฉันหมายเลขพอร์ตสำหรับวัตถุที่สร้างขึ้นไม่พร้อมใช้งานดังนั้นฉันจึงคิดสิ่งนี้ขึ้นมา

IPEndPoint endPoint;
int port = 1;
while (true)
{
    try
    {
        endPoint = new IPEndPoint(IPAddress.Any, port);
        break;
    }
    catch (SocketException)
    {
         port++;
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.