socket编程:TCP、UDP传字符串

初次接触socket编程,平时用java用得也少,对输入输出流不太了解,做实验时记录一下。可能对小白也有帮助。


一、利用TCP传字符串

1、代码

利用TCP从client端传字符串到server端,转换成大写后返回给client端显示,代码如下,略去导入部分:

​
客户端:
public class TCPClient {
	public static void main(String argv[]) throws UnknownHostException, IOException {
		String sentence;
		String modifiedSentence;
		BufferedReader informUser=new BufferedReader(new InputStreamReader(System.in));//定义字符输入流对象,从键盘读入数据
		Socket clientSocket=new Socket("localhost",6789);//定义client端地址与端口
		DataOutputStream outToServer=new DataOutputStream(clientSocket.getOutputStream());//给socket赋予输出流
		BufferedReader infromServer=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));//给socket赋予输入流
		sentence=informUser.readLine();//获取键盘输入流中的字符串
		outToServer.writeBytes(sentence+'\n');//socket输出到服务端     面向字符流,可以直接发送String类型
		modifiedSentence=infromServer.readLine();//从服务端获取字符串
		System.out.println("from server :"+modifiedSentence);//打印到控制台
		clientSocket.close();//关闭socket
	}
}




​
服务端:
public class TCPServer {
	public static void main(String argv[]) throws IOException {
		String Clientsentence;
		String capitalizedSentence;
		ServerSocket welcomeSocket=new ServerSocket(6789);//创建绑定到特定端口的serversocket
		while(true) {//当有其他进程时都建立连接
			Socket connectionSocket=welcomeSocket.accept();//持续监听,连接到后返回socket连接对象
			BufferedReader infromClient=new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));//在为连接设置输入流
			DataOutputStream outToClient=new DataOutputStream(connectionSocket.getOutputStream());//连接设置输出流
			Clientsentence=infromClient.readLine();//从客户端获取数据
			capitalizedSentence =Clientsentence.toUpperCase()+'\n';//转化成大写
			outToClient.writeBytes(capitalizedSentence);//输出到客户端

		}
	}
}

2、代码分析:

①Java类解释:

BufferedReader   定义字符输入缓冲流,从字符输入流中读取文本,在创建具体流时需要给出一个InputStream / OutputStream                                类型的流座位前端流,并可以指明缓冲区的大小。

System.in            System.in对应的是标准输入设备,键盘。

InputStreamReader   InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。

Socket                定义socket连接,在client初始化时要传递主机名和端口名。

DataInputStream         数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。

DataOutputStream      数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。

②流程分析:

     在client端,先定义Socket利用目的主机名/IP地址和端口号进行初始化,利用Socket.getInputStream()和socket.getOutputStream()初始化输入输出流,需要缓冲区可以设置为BufferedReader和BufferedWriter类,不需要缓冲区设置为DataInputStream和DataOutputStream类。利用输出流的write方法向server端发送数据,利用输入流的read方法从server端接受数据。

     在server端,先定义ServerSocket对象并绑定端口,此时开始监听,监听到连接时用ServerSocket的accept方法返回Socket对象建立连接,然后定义输入输出对象进行数据传输操作。

实验效果如下:

 二、利用UDP传字符串

1、代码

利用UDP从client端传字符串到server端,转换成大写后返回给client端显示,代码如下,略去导入部分:

客户端:
public class UDPClient {
	public static void main(String args[]) throws IOException {
		BufferedReader inFromUser=new BufferedReader(new InputStreamReader(System.in));//定义从键盘输入比特流
		DatagramSocket clientSocket=new DatagramSocket();//定义UDP数据报
		InetAddress IPAddress=InetAddress.getByName("localhost");//获取地址
		String sentence=inFromUser.readLine();
		byte[] sendData=new byte[sentence.length()];
		byte[] receiveData=new byte[1024];
		sendData=sentence.getBytes(); //面向字节流,要发送byte数据
		DatagramPacket sendPacket=new DatagramPacket(sendData,sendData.length,IPAddress,9876);//定义发送数据报包
		clientSocket.send(sendPacket);//利用socket发送数据报包
		DatagramPacket receivePacket=new DatagramPacket(receiveData,receiveData.length);//定义接收包
		clientSocket.receive(receivePacket);//socket接收数据赋值给接收包
		String modifiedSentence=new String(receivePacket.getData());//获取包中数据
		System.out.println("from server:"+modifiedSentence);//输出
		clientSocket.close();//关闭
		}
}




服务端:
public class UDPServer {
	public static void main(String args[]) throws IOException {
		@SuppressWarnings("resource")
		DatagramSocket serverSocket =new DatagramSocket(9876);//定义数据报UDP
		byte[] receiveData=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 capitalizedSentence =sentence.toUpperCase();//转化成大写
			byte[] sendData=new byte[capitalizedSentence.length()];
			sendData=capitalizedSentence.getBytes();//转换成byte流
			
			DatagramPacket sendPacket=new DatagramPacket(sendData,sendData.length,IPAddress,port);//定义发送包
			serverSocket.send(sendPacket);//发送
		}
	}
}

代码分析:

①Java类解释:

DatagramSocket     用户数据报socket类,收到的数据通过receive()方法保存到DatagramPacket对象中。

DatagramPacket     数据报包类,可以用DatagramPacket (byte[]buf, intlength)初始化,指定数据包的内存空间和大小,可用于接收。DatagramPacket(byte[]buf, intlength , InetAddressaddress , intport)构造函数不仅指定了数据包的内存空间和大小,而且指定了数据包的目标地址和端口,可用于发送。

InetAddress           没有构造方法,可以用InetAddress.getByName("")初始化对象,保存IP地址和域名

②流程分析:

Client端DatagramSocket对象本身不绑定端口,使用send方法发送带有目标地址和端口的DatagramPacket   对象进行传输。Server端DatagramSocket初始化时绑定端口,使用receive()方法收到数据报包后交给自定义接收包,使用DatagramPacket的getData()方法获得数据,getAddress()方法获得来源地址,getPort()方法获得来源端口。进行处理后再定义DatagramPacket进行传输。

实验效果如下:

 三、小结

TCP和UDP编程的区别和相似点:

相似点:

1、server端都对特定端口进行绑定,使用IP+端口号确定目标。

2、都进行字节流/比特流传输,因此传输字符串2要进行转换。建议使用String.getBytes()进行转换,使用write方法进行发送,使用writeBytes直接传输字符串时由于中文一个字符占两个字节会导致高8位丢失,出现乱码。

区别:

1、TCP编程传输单位是字节流,UDP是DatagramPacket,要把字节流存到DatagramPacket包中。这是由于UDP不是面向连接的协议,需要每次都传目标地址+端口造成的,而TCP只要在初始化socket时绑定就行。

2、在传输文本对象时,TCP可以利用BufferedReader等对文本进行缓冲读取,UDP依然要通过byte[]初始化DatagramPacket对象进行存储。传输其他的二进制文件时,TCP也要用DataInputStream和DataOutputStream进行比特流传输。

 

后文:socket编程(二):TCP传文本文件、传二进制文件

你可能感兴趣的:(socket编程:TCP、UDP传字符串)