你最愿意做的哪件事,才是你的天赋所在

0%

java学习之路4-Socket

TCP

服务端

TCP的数据传送使用的是流,也就是通过DataInputStream,DataOutputStream来传递。
在服务器端,我们需要绑定监听端口,然后就可以获取该端口的输入流和输出流。
ServerSocket 是创建一个socket的服务,指定监听窗口。
然后用该对象能够返回一个Socket,通过这个Socket中的信息来通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package Socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.*;
public class Server {

public static void main(String[] args) {
ServerSocket socket = null;
Socket socket2 = null;
try {
//此处可以直接改为try-with-resoutce形式,避免使用finally语句关闭资源
socket = new ServerSocket(8000);
//创建一个ServerSocket对象,指定监听端口,与客户端程序保持一致
System.out.println("Listening on port 8000");
socket2 = socket.accept();
//监听并等待接受连接:accept
DataInputStream in = new DataInputStream(socket2.getInputStream());
DataOutputStream out = new DataOutputStream(socket2.getOutputStream());
//创建Data Input/Output 流
double radius = in.readDouble();
//从客户端接受圆的半径(通过DataInput流读取)
double area = radius*radius*Math.PI;
//计算圆的面积
out.writeDouble(area);
//把圆面积发给客户端
System.out.println("Send Area:"+area+" to client");
//输出提示信息
// 加入while循环,使得服务器不断接收半径并且发送面积
// 从客户端接受圆的半径
//半径小于0,则退出循环
//计算圆的面积
//把面积发送给客户端
//输出提示信息
in.close();
out.close();
socket2.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}finally {
}
}

}

在客户端,我们需要发送信息,就要指定IP地址和端口号。如果是本地的话就是’localhost’。

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package Socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.DatagramSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Scanner;

import unit09.*;
public class ClientSocket {
public static void main(String[] args)
{
Socket socket = null;
Scanner scanner = new Scanner(System.in);
//创建一个Socket对象,连接到服务器,端口号,IP地址
try {
//创建一个Socket,里面指明发送的地址(地址包含IP地址和端口号)
socket = new Socket("localhost", 8000);
//创建一个Data Stream 输入流对象,从服务器读取数据
DataInputStream in = new DataInputStream(socket.getInputStream());
//创建一个data Stream 输出流对象,向服务器发送数据
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
//提示并从键盘读入一个浮点数作为圆的半径
double radius=scanner.nextDouble();
//将半径发送给服务器,并且提示
out.writeDouble(radius);
System.out.println("Sent radius: "+radius+" to Server ");
double area = in.readDouble();
//从服务器读取圆面积,并且显示
System.out.println("Receive area:"+area);
} catch (Exception e) {
e.printStackTrace();
}
}
}

UDP

UDP的连接是通过DatagramPacket来传递的,里面包含有传递需要的信息,字节数组,字节数组的长度以及IP地址和端口号等等

服务端

在服务端,我们需要创建一个DatagramSocket(int port)的实例,然后使用这个实例来发送Packet和接受Packet。
如果想要对接受到的信息做出回应,在接受到的Packet中,会包含该IP地址和端口号,可以通过SetAddress和SetPort来设置发送的地址,然后使用DatagramSocket来发送就好了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package Socket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Arrays;
import java.util.Date;
public class Demo09P7S {
public static void main(String[] args) throws IOException {
// The byte array for sending and receiving datagram packets
byte[] buf = new byte[1024];
byte[] sendbuf = new byte[1024];
// Create a packet for receiving data with DatagramPacket(buffer, length)
DatagramPacket recvPacket = null;
// Create a packet for sending data with DatagramPacket
DatagramPacket sendPacket = null;
// Create a server socket with DatagramSocket(port)
DatagramSocket socket = new DatagramSocket(8000);
// Print information about server started
System.out.println("Server started on port 8000, " + new Date());
while (true) {
// Initialize buffer for each iteration with Arrays.fill()
Arrays.fill(buf, (byte)0);
Arrays.fill(sendbuf,(byte)0);
// Assign data to the received packet
recvPacket = new DatagramPacket(buf, buf.length);
// Receive radius from the client socket in a packet, call receive()
socket.receive(recvPacket);
// Print the client hostname and port number with DatagramPacket.getAddress/getPort
sendPacket = new DatagramPacket(sendbuf, sendbuf.length);
sendPacket.setAddress(recvPacket.getAddress());
sendPacket.setPort(recvPacket.getPort());
System.out.println("Received packet from ");
// use Double.parseDouble to transfer byte[] to double
double radius = Double.parseDouble(new String(buf));
System.out.println("Radius: " + radius);
// Compute area
double area = radius * radius * Math.PI;
System.out.println("Area is " + area + '\n');
// Send area to the client in a packet, with DatagramPacket.setAddress/setPort/setData/send
sendbuf = Double.valueOf(area).toString().getBytes();

// TODO 鍙戦�佺殑鏁扮粍鍙兘瓒呰繃涓�涓狣ouble澶у皬锛屾鏌ユ敹绔槸鍚︽纭帴鏀�

// Assign data to the packet sending to client with setData
sendPacket.setData(sendbuf);
// send the packet
socket.send(sendPacket);
System.out.println("Area sent.");
} // end while
} // end main
}

客户端

客户端的DatagramSocket不需要指明端口号,因为需要发送的时候,JVM会随机一个可用的端口号来使用。
只需要把发送的信息封装到packet中就好了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package Socket;

import java.io.*;
import java.net.*;
import java.util.*;
public class Demo09P7C {
public static void main(String[] args) {
// The byte array for sending and receiving datagram packets
byte[] buf = new byte[1024];
// Server InetAddress
InetAddress server = null;
// The packet sent to the server
DatagramPacket sendpacket = null;
// The packet received from the server
DatagramPacket recvpacket = null;

// get a DatagramSocket socket
try (DatagramSocket socket = new DatagramSocket()){
// get the Server address with InetAddress.getByName
server=InetAddress.getByName("10.128.227.70");
// Create a send packet with DatagramPacket(buffer, length, InetAddress, port)
// Or create DatagramPacket with buffer and length, with server address/port set later
// Create a receive packet with DatagramPacket(buffer, length)
recvpacket= new DatagramPacket(buf, buf.length);
// Initialize buffer for each iteration with Arrays.fill
Arrays.fill(buf, (byte)0);

// 输入圆的半径 with Scanner
System.out.println("Please input radius : ");
Scanner scanner = new Scanner(System.in);
double r = scanner.nextDouble();
// Transfer double number to byte[] with Double.valueOf() and String.getBytes()
buf=Double.valueOf(r).toString().getBytes();
// assign the byte[] buf to packet with DatagramPacket.setData
sendpacket = new DatagramPacket(buf, buf.length,server,8000);
// send the packet with DatagramSocket.send(DatagramPacket)
int cnt = 0;
while(cnt<1000)socket.send(sendpacket);
// receive area from the server in a packet with DatagramSocket.receive(DatagramPacket)
buf = new byte[1024];
Arrays.fill(buf, (byte) 0);
recvpacket = new DatagramPacket(buf, buf.length);
socket.receive(recvpacket);
// Transfer byte[] to double with Double.parseDouble and String(byte[])
double area=Double.parseDouble(new String(buf));
// Display radius and area.
System.out.println("Radius is " + r + "\n");
System.out.println("Area received from the server is " + area
+ '\n');
scanner.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

-------------你最愿意做的哪件事才是你的天赋所在-------------