B/S结构和C/S结构
服务器socket
- Socket是服务器对外的接口(插座)
- Socket要与端口绑定
- 端口是什么?
操作系统分配的一种“号”资源
用于区分从网卡传入的数据包
根据“包”中的“端口号”,操作系统将该“包”转发到相应服务程序
端口号:0 ~ 1023被预先定义的服务通信占用;用户程序用1024~65535
如何定义socket(套接字)
ServerSocket serverSocket = new ServerSocket(port)//port是端口
Socket soc = new Socket (“127.0.0.1”, 80);
Socket soc = new Socket (“130.254..22.1”, 80,“130.254.22.1”,2001);
通过socket进行简单数据传输
1)服务端客户端建立联系
- 服务端代码:
ServerSocket server = new ServerSocket(8000);
Socket socket = server.accept(); - 客户端代码:
Socket socket = new Socket(host,8000);
2)通过输入输出流进行网络数据传递
- socket. getInputStream();
- socket.getOutputStream();
3)通过与socket关联的输入输出流进行直接通讯
- DataOutputStream out = new DataOutputStream(socket.getOutputStream());
- out.writeChars(“heelwuroewruowruweoru!”);
- out.writeUTF(“heelwuroewruowruweoru!”);
4)使用输入流读取信息
- DataInputStream in = new DataInputStream(socket.getInputStream());
- in.readUTF(); //返回String 若无信息返回NULL
- in.readchar(); //返回字符
网络协议
- IP(Internet Protocol,Internet协议)
- TCP(Transport Control Protocol,传输控制协议)
- UDP(User Datagram Protocol,用户数据报协议)
A Client/Server Example
- 服务器功能需求:
从客户端接收圆“半径值”
计算机圆面积
将面积反馈给客户端 - 客户端功能:
用户输入半径
将半径发送至服务器
获取服务器返回的面积值并显示 - 执行过程
1)服务器启动,界面提示:服务器于几点几分启动
2)客户端启动
3)用户输入半径并按下“输入半径”按钮
4)客户端发送数据
5)服务端获得数据并产生提示信息
6)服务端将计算结果发送到客户端
7)客户端接收并显示
//Client
package round;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
//https://blog.csdn.net/hongkangwl/article/details/15810599
public class Client extends JFrame implements ActionListener{
private JTextField jtf = new JTextField();//单行文本
private JTextArea jta = new JTextArea();//多行文本
private DataOutputStream outputToServer;
private DataInputStream inputFromServer;
public static void main(String[] args) {
new Client();
}
public Client(){
JPanel p = new JPanel();//JPanel是一个容器类,为了放置文本框和标签
p.setLayout(new BorderLayout());
p.add(new JLabel("输入圆的半径:"), BorderLayout.WEST);
p.add(jtf, BorderLayout.CENTER);
jtf.setHorizontalAlignment(JTextField.RIGHT);//setHorizontalAlignment:设置水平对齐方式
getContentPane().setLayout(new BorderLayout());
getContentPane().add(p, BorderLayout.NORTH);
getContentPane().add(new JScrollPane(jta), BorderLayout.CENTER);
jtf.addActionListener(this);//监听事件
setTitle("Client");
setSize(500, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
try {
Socket socket = new Socket("localhost", 8000);
inputFromServer = new DataInputStream(socket.getInputStream());
outputToServer = new DataOutputStream(socket.getOutputStream());
}
catch (IOException ex) {
jta.append(ex.toString() + '\n');
}
}
@Override
public void actionPerformed(ActionEvent e){
if (e.getSource() instanceof JTextField) {
try {
double radius = Double.parseDouble(jtf.getText().trim());//trim()方法来减少用户输入的多余空格,这不是必须的,但是能使程序更加健壮
outputToServer.writeDouble(radius);
outputToServer.flush();
double area = inputFromServer.readDouble();
jta.append("圆的半径是 " + radius + '\n');
jta.append("圆的面积是 " + area + '\n');
}
catch (IOException ex) {
System.err.println(ex);
}
}
}
}
//Server
package round;
import java.io.*;
import java.net.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;
public class Server extends JFrame{
private JTextArea jta = new JTextArea();//JTextArea 多行文本框
public static void main(String[] args) {
new Server();
}
public Server(){
//定义容器Container con=getContentPane();
// 用getContentPane()方法获得JFrame的内容面板,再对其加入组件
getContentPane().setLayout(new BorderLayout());
getContentPane().add(new JScrollPane(jta), BorderLayout.CENTER);//JFrame默认布局是BorderLayout,东西南北中
setTitle("Server");
setSize(500, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户单击窗口的关闭按钮时程序执行的操作
setVisible(true);//设置窗体可见,没有该语句,窗体将不可见,此语句必须有,否则没有界面就没有如何意义了
try {
//
ServerSocket serverSocket = new ServerSocket(8000);
jta.append("Server started at " + new Date() + '\n');
//创建与客户端的连接
Socket socket = serverSocket.accept();
//数据的输入、输出流
DataInputStream inputFromClient = new DataInputStream(socket.getInputStream());
DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream());
while (true){
//获得输入流
double radius = inputFromClient.readDouble();
double area = radius * radius * Math.PI;
//将计算结果输出到客户端
outputToClient.writeDouble(area);
jta.append("从客户端接收圆的半径:" + radius + '\n');
jta.append("圆的面积:" + area + '\n');
}
}
catch(IOException ex) {
System.err.println(ex);
}
}
}