您的位置:首页 > 理论基础 > 计算机网络

TCP和UDP套接字编程

2015-01-29 21:25 316 查看
下面会使用简单的客户机/服务器应用程序来分别演示使用TCP套接字编程和UDP套接字编程。

先说明一下,实现的功能:

(1)一台客户机从键盘读取一行字符,并通过连接的套接字发送给服务器

(2)服务器从套接字读取该行字符

(3)服务器将该行字符的小写字符,转换成大写字符

(4)服务器将转换后的字符通过连接的套接字返回给客户机

(5)客户机从其套接字读取转换后的字符后,通过监视器打印出来。

下面先看一下TCP套接字编程:

TCPServer:

public class TcpServer {

public static void main (String arg[])throws Exception{


String clientSentence;


String ModifiedSentence;


ServerSocket welcomeSocket = new ServerSocket(6789);


while(true){


Socket connectionSocket = welcomeSocket.accept();


BufferedReader isFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));


DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());


clientSentence = isFromClient.readLine();


ModifiedSentence = clientSentence.toUpperCase()+'\n';


outToClient.writeBytes(ModifiedSentence);


}
}
}
ServerSocket welcomeSocket = new ServerSocket(6789);
通常我们把Socket当作一扇门,而这一句则是监听某客户机“敲门”声的门,而且是在6789端口上监听。

Socket connectionSocket = welcomeSocket.accept();




这句表示,当某客户机“敲门”时,则创建一个新的套接字。这时,connectionSocket已经和客户机某socke创建了虚拟管道,它们都可以通过其发送直接。

BufferedReader isFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
clientSentence = isFromClient.readLine();
这两行则读取了客户机的输入。

ModifiedSentence = clientSentence.toUpperCase()+'\n';
这一行完成了将客户机发来的字符,转换成大写字符

DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
outToClient.writeBytes(ModifiedSentence);
这两行则往客户机返回数据。

TCPClient:

public class TcpClient {

public static void main(String[] args)throws Exception{


String sentence;


String modifiedSentence;


BufferedReader isFromUser = new BufferedReader(new InputStreamReader(System.in));


Socket clientsSocket = new Socket(InetAddress.getLocalHost(), 6789);


DataOutputStream outToServer= new DataOutputStream(clientsSocket.getOutputStream());


BufferedReader isFromServer = new BufferedReader(new InputStreamReader(clientsSocket.getInputStream()));


sentence = isFromUser.readLine();


outToServer.writeBytes(sentence+'\n');


modifiedSentence = isFromServer.readLine();

System.out.println("From Server:" + modifiedSentence);


clientsSocket.close();


}
}


BufferedReader isFromUser = new BufferedReader(new InputStreamReader(System.in));
sentence = isFromUser.readLine();



这两行是读取用户从键盘上输入的东西,并转换成字符串类型,放在sentence。

Socket clientsSocket = new Socket(InetAddress.getLocalHost(), 6789);
创建了与服务器连接的Socket,通过该行也发起了客户机和服务器间的TCP连接。由于本次测试是在客户机,服务器都是本主机,所以IP地址是InetAddress.getLocalHost(),即本地IP地址。6789表示连接服务器上的端口号。

DataOutputStream outToServer= new DataOutputStream(clientsSocket.getOutputStream());
outToServer.writeBytes(sentence+'\n');
这两行是把用户输入的文本发送到服务器上。

BufferedReader isFromServer = new BufferedReader(new InputStreamReader(clientsSocket.getInputStream()));
modifiedSentence = isFromServer.readLine();
System.out.println("From Server:" + modifiedSentence);
这三行是读取服务器返回的信息,并打印在监视器上。

clientsSocket.close();
该行关闭了套接字,因此客户机和服务器之间的TCP连接也同时被关闭。这一行会引起客户机向服务器发送运输层报文。

注意这里应该先运行编译好的服务器程序,在运行客户机的程序,结果如下:

假设输入为abc

abc
From Server:ABC


然后用UDP套接字编程实现同样的功能:

UDPServer:

public class UDPServer {
public static void main(String args[]) throws Exception {
DatagramSocket serverSocket = new DatagramSocket(9999);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
while (true) {
DatagramPacket receivePacket = new DatagramPacket(receiveData,
receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String(receivePacket.getData());
InetAddress ipAddress = receivePacket.getAddress();int port = receivePacket.getPort();
String modifiedSentence = sentence.toUpperCase();
sendData = modifiedSentence.getBytes();
DatagramPacket sendDatagramPacket = new DatagramPacket(sendData,
sendData.length, ipAddress, port);
serverSocket.send(sendDatagramPacket);
} }
}


DatagramSocket serverSocket = new DatagramSocket(9999);
该行在端口9999构造了DatagramSocket对象,应该注意到这用到的套接字与TCP不一样。因为UDP是无连接的,所以当接受时,没有必要像TCP那样产生一个新的套接字并继续监听请求。如果有多个客户机访问该服务器端口,都将往这个单一的门发送分组。

DatagramPacket receivePacket = new DatagramPacket(receiveData,receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String(receivePacket.getData());
这几行是读取客户机发送过来的数据,并放在sentence上。

InetAddress ipAddress = receivePacket.getAddress();
<pre name="code" class="java">int port = receivePacket.getPort();



这一行是获取客户机的ip地址和端口。以便给客户机返回数据。

DatagramPacket sendDatagramPacket = new DatagramPacket(sendData,sendData.length, ipAddress, port);
serverSocket.send(sendDatagramPacket);
这两行则是把转换结果发送给客户机。注意该分组应该包含IP地址与端口。

UDPClient:

public class UDPClient {
public static void main(String args[])throws Exception{
BufferedReader isFromUser = new BufferedReader(new InputStreamReader(System.in));
DatagramSocket clientSocket = new DatagramSocket(11111);
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
String sentence = isFromUser.readLine();
sendData = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getLocalHost(), 9999);
clientSocket.send(sendPacket);
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
String modifiedSentence = new String(receivePacket.getData());
System.out.println("From Server:"+modifiedSentence);
clientSocket.close();
} }


DatagramSocket clientSocket = new DatagramSocket(11111);
该行,是为UDP套接字指派了一个特定的端口号11111,当然也可以不指定端口号,则不填参数即可,这时,运输层自动为该套接字分配一个尚未使用的端口号。

DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getLocalHost(), 9999);
该行构件了一个分组,包含数据,数据长度,服务器IP地址(因为本测试在本主机运行,所以用本地IP地址),以及端口号

clientSocket.close();
关闭套接字,因为UDP无连接的,所以不会引起客户机向服务器发送运输层报文。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: