Professional Documents
Culture Documents
อ. วัจนพงศ เกษมศิริ
ภาควิชาวิศวกรรมคอมพิวเตอร
สถาบันเทคโนโลยีพระจอมเกลาเจาคุณทหารลาดกระบัง
4. Connectionless Socket
Connectionless Sockets เปน Socket ซึ่งใช UDP Protocol เปน Protocol ในการสื่อสาร ดังนั้นเนื้อหาใน
บทนี้จะแบงเปน 2 สวนดวยกันคือ UDP Protocol โดยสรุป และการสรางและทํางานกับ Connectionless Socket
UDP Source PORT (16 bits) UDP Destination PORT (16 bits)
UDP Message Length (16 bits) UDP Checksum (16 bits)
Data
...
i. UDP Source Port: field นี้มีขนาด 16 bits และมีลักษณะเปน Optional คือจะใสขอมูล port หรือไมใสก็ได
หากใสขอมูล port ก็จะเปนการระบุวาการตอบกลับจากเครื่องปลายทางจะใหสงมาที่หมายเลข port นี้
ii. UDP Destination Port: เปน field ที่มีขนาด 16 bits ใชระบุหมายเลข port ปลายทาง
iii. UDP Message Length: เปน field ที่มีขนาด 16 bits ใชระบุความยาวของขอมูลที่จะสง
iv. UDP Checksum: มีขนาด 16 bits ใชสําหรับใสคา checksum โดยการคํานวณ checksum นั้นจะคํานวณทั้ง
Message กลาวคือนําทั้งสวน header และ สวน data มาทําการคํานวณ สําหรับสวน UDP Checksum นี้เปน
Optional หากไมใชจะใสคาใน field นี้เปน 0 การทําใหสามารถเลือกที่จะไมใช checksum ก็เพื่อที่จะลด
การคํานวณลงในกรณีที่การสื่อสารนั้นกระทําบนเครือขายที่มีความนาเชื่อถือสูง
4.1.3 UDP Encapsulation and Protocol Layering
ในการทํางาน UDP จะอยูในชั้น (layer) เหนือชั้น IP ตามรูป 4.2 ซึ่งนั่นจะไดวา โปรแกรมประยุกตจะ
ปอนขอมูลที่ตองการสงใหกับชั้นของ UDP และ UDP จะอาศัยกลไกของ IP ในการนําขอมูลไปยังปลายทาง การ
ที่ชั้นของ UDP อยูบนชั้นของ IP นั้นจะไดวา Package ของ UDP (ทั้ง header และ data) จะบรรจุไวในสวน Data
ของ IP ซึ่งจะเปน package ที่จะสงออกไปยังเครือขายภายนอกตอไป ตามรูป 4.3
Application
UDP
IP
Network Interface
D2
D1 D3
UDP Multiplexing
H3 D3
H2 D2
H1 D1
IP Layer
UDP De-multiplexing
UDP Datagram
IP Layer
4.2.1.1 SendTo()
เปน method ซึ่งใชในการสงขอมูลไปยังเครื่องปลายทาง โดยการใช SendTo() นั้นสามารถใส parameter
ไดในหลายลักษณะ ดังนี้
สําหรับรูปแบบนี้จะรับ parameter SocketFlags เพิ่มเขามา ซึ่ง SocketFlags นี้จะใชเพื่อระบุ UDP Socket Option ที่
จะเลือกใชงาน
ในรูปแบบนี้จะมีการระบุจํานวนไบตที่ตองการจะสงเพิ่มเขามา โดยจํานวนไบตที่ตองการจะสงนั้นจะระบุลงใน
ตัวแปรชนิด integer ชื่อ Size
SendTo(byte[] data, int Offset, int Size, SocketFlags Flags, EndPoint Remote)
4.2.1.2 ReceiveFrom()
เปน Method ที่ใชสําหรับการรับขอมูล โดยจะรับ parameter 2 ตัวไดแก byte array ที่ทําหนาที่เปน data
buffer และ EndPoint ของเครื่องปลายทาง โดยรูปแบบการใชงาน ReceiveFrom() เปนดังนี้
newsock.Bind(ipep); //11
จากตัวอยางจะพบวา
- ในขั้นตอนสราง Socket
o ใช SocketType เปน SocketType.Dgram
o ใช ProtocolType เปน ProtocolType.Udp
- เมื่อตองการใหโปรแกรมที่สรางขึ้นสามารถรับขอมูลไดตองมีขั้นตอนการ bind
- ไมมีขั้นตอนของการ connect
- ในการสรางตัวแปร Remote เพื่อเปน parameter ใหกับ ReceiveFrom() นั้นจะทําการสราง Object
sender ซึ่งเปนชนิด IPEndPoint ขึ้นมาโดยกําหนดคาให sender บรรจุ IPEndPoint วาง ๆ เอาไว
จากนั้น assign คา sender ใหกับ Remote โดยทําการแปลง Type จาก IPEndPoint เปน EndPoint
(ดังในตัวอยางโปรแกรมในบรรทัดที่ 13-14-15)
- ใช SendTo() และ ReceiveFrom() ในการรับ – สงขอมูล
ขอสังเกต
จากที่ไดกลาวไวตอนตน การเชื่อมตอแบบ Connectionless นี้ ใช Protocol สําหรับการสื่อสาร UDP
ดังนั้นจึงไมมีการสราง virtual connection ระหวางเครื่องสงและเครื่องรับ ดังนั้นหากเครื่อง client จบการทํางาน
และปด socket ไป โปรแกรมทางฝงของ server ก็ไมอาจทราบไดวาฝง client นั้นไดปด socket ไปแลว และจะ
ยังคงรอรับการติดตอจาก Client ตอไป
class SimpleUdpClient
{
public static void Main()
{
byte[] data = new byte[1024];
string input, stringData;
IPEndPoint ipep = new IPEndPoint(
IPAddress.Parse("127.0.0.1"), 9050);
while(true)
{
input = Console.ReadLine();
if (input == "exit")
break;
server.SendTo(Encoding.ASCII.GetBytes(input), Remote);
data = new byte[1024];
recv = server.ReceiveFrom(data, ref Remote);
stringData = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(stringData);
}
Console.WriteLine("Stopping client");
server.Close();
}
}
class ConnectUdpClient
{
public static void Main()
{
byte[] data = new byte[1024];
string input, stringData;
IPEndPoint ipep = new IPEndPoint(
IPAddress.Parse("127.0.0.1"), 9050);
server.Connect(ipep);
string welcome = "Hello, are you there?";
data = Encoding.ASCII.GetBytes(welcome);
server.Send(data);
class TestUdpSrvr
{
public static void Main()
{
int recv;
byte[] data = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);
newsock.Bind(ipep);
Console.WriteLine("Waiting for a client...");
class TestUdpClient
{
public static void Main()
{
byte[] data = new byte[1024];
IPEndPoint ipep = new IPEndPoint(
IPAddress.Parse("127.0.0.1"), 9050);
Console.WriteLine("Stopping client");
server.Close();
}
}
class BadUdpClient
{
public static void Main()
{ 1
byte[] data = new byte[30];
string input, stringData;
IPEndPoint ipep = new IPEndPoint(
IPAddress.Parse("127.0.0.1"), 9050);
while(true)
{
input = Console.ReadLine();
if (input == "exit")
break;
server.SendTo(Encoding.ASCII.GetBytes(input), tmpRemote);
data = new byte[30];
recv = server.ReceiveFrom(data, ref tmpRemote);
stringData = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(stringData);
}
Console.WriteLine("Stopping client");
server.Close();
}
}
class BetterdUdpClient
{
public static void Main()
{
byte[] data = new byte[30];
string input, stringData;
IPEndPoint ipep = new IPEndPoint(
IPAddress.Parse("127.0.0.1"), 9050);
iii. Retransmission
เมื่อสามารถตรวจจับการสูญหายของขอมูลไดโดยการตั้งคา Time-Outs และ Catch Exception ซึ่งเกิด
จากการ time-outs ไดก็อาจสราง method ขึ้นมาเพื่อ retransmission ซึ่งสูญหายนั้นอีกครั้ง ดังในโปรแกรมตัวอยาง
4.8
while (true)
{
Console.WriteLine("Attempt #{0}", retry);
try
{
s.SendTo(message, message.Length, SocketFlags.None, rmtdevice);
data = new byte[size];
recv = s.ReceiveFrom(data, ref Remote);
} catch (SocketException e)
{
if (e.ErrorCode == 10054)
recv = 0;
else if (e.ErrorCode == 10040)
{
Console.WriteLine("Error receiving packet");
size += 10;
recv = 0;
}
}
if (recv > 0)
{
return recv;
} else
{
retry++;
if (retry > 4)
{
return 0;
}
}
}
}
while(true)
{
input = Console.ReadLine();
if (input == "exit")
break;
recv = AdvSndRcvData(server, Encoding.ASCII.GetBytes(input), ipep);
if (recv > 0)
{
stringData = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(stringData);
} else
Console.WriteLine("Did not receive an answer");
}
Console.WriteLine("Stopping client");
server.Close();
}
}