黑马程序员 Java网络编程

本文介绍了一个基于TCP/IP协议的铁路售票系统,包括本地回路的IP地址、端口号、TCP与UDP协议、Socket机制及其在服务器端与客户端间的通信流程。详细描述了如何通过Socket实现服务器端与客户端之间的数据传输,以及如何使用DatagramSocket进行UDP通信。同时,展示了通过Windows的telnet程序测试TCP服务程序的功能,并讨论了使用BufferedReader进行文本读取的方法。最后,介绍了HTTP消息头的作用以及一个简单的铁路网上排队购票模拟系统的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

------- android培训java培训、期待与您交流! ----------

1本地回路的IP地址:127.0.0.1,可以在控制台中输入ping 127.0.0.1来检测本地计算机中的TCP/IP协议是否安装正确,这个IP并未与网卡绑定,可以利用这个IP地址来实现同一台计算机上的两个网络应用程序的通信。
2Port(端口号),端口号的范围为0—65535之间,0—1023之间的端口数是用于一些知名的网络服务和应用。不同的应用程序接收不同端口的数据,同一台计算机上不能有两个使用同一个端口的应用程序。计算机接收到一个网络数据包以后,驱动程序根据数据包中的端口号来确定应该把这个数据包交给哪个程序来处理。
3TCP,传输控制协议,是面向连接的通信协议,它提供两台计算机之间可靠和无差错的数据传输。
4,UDP,用户数据报协议,是无连接通信协议。UDP不保证数据的可靠传输,但能够向若干个目标发送数据和接收发至若干个源的数据,如果一个主机向另外一台主机发送UDP数据,这个数据就会立刻发送出去,而不管另外一台主机是否已经准备接收数据,网络线路繁忙或出现故障时会造成UDP数据包的丢失。如果另外一台主机接收到了数据,它不会确认收到与否。
5Socket是网络驱动层提供给应用程序编程的接口和一种机制,可以把Socket比喻成一个港口码头。应用程序只要把货物放到港口码头上,就算完成了货物的运送。应用程序只需等待货物到达码头后,将货物取走。Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IPPort。不能使用Socket类的构造方法来创建服务器端的Socket对象。服务器端的Socket对象是ServerSocket.accept在接收到客户端的连接请求后返回的。
6DatagramSocket类用于UDP通信,示例:DatagramSocket s = new DatagramSocket(null); s.bind(newInetSocketAddress(8888)); 这等价于:DatagramSocket s = new DatagramSocket(8888);两个例子都能创建能够在 UDP 8888端口上接收广播的 DatagramSocket
7ServerSocket类用于TCP通信的服务器端。
8Socket类用于TCP通信的服务器和客户端。这个服务器端指的是一个专用于和客户端建立数据传输的Socket,而ServerSocket是指接收客户端的连接的。

Socket数据发送过程:


Socket数据接收过程:

9TCP客户端与TCP服务器端程序的交互过程:
1)服务器程序创建一个ServerSocket,然后调用accept方法等待客户来连接。
2)客户端程序创建一个Socket并请求服务器建立连接。
3)服务器接收客户的连接请求,并创建一个新的Socket与该客户建立专线连接。
4)建立了连接的两个Socket在一个单独的线程(由服务器程序创建)上对话。
5)服务器开始等待新的连接请求,当新的连接请求到达时,重复步骤(2)到步骤(5)的过程。
10可以使用Windows提供的telnet程序测试TCP服务程序。当使用telnet向服务程序发送数据时,控制台中若没有显示你所输入的字符,那就可以通过打开telnet程序的本地回显功能来看到你输入的字符。
11使用BufferedReader包装类,从网络输入流中一次读取一行文本。
12使用netstat命令查看当前正在被使用的TCP端口号。
13ObjectInputStreamObjectOutputStream可以从底层输入流中读取对象类型和数据和将对象类型的数据写入到底层输出流,使用ObjectInputStreamObjectOutputStream来包装底层网络字节流,TCP服务器和TCP客户客户端之间就可以传递对象类型的数据。

14HTTP的几个消息头
1Connection用于指定处理完本次请求/响应后,客户端与服务器是否继续保持连接。设置值可以为Keep-Aliveclose
2Accept-Language用于指出客户机期望服务器返回的文档所使用的国家语言,可以指定多个以逗号分隔的国家语言。
3Cotent-Length用于表示实体内容的长度(字节数)。
4Range用于指定服务器只需返回文档中的部分内容及内容范围。
5Content-Range用于指定服务器返回的部分实体内容的位置信息。

15下面是我做的一个模拟铁路网上排队购票的系统,做得不好,呵呵

服务器端

1.    package com.itheima.bzx;  

2.      

3.    import java.awt.*;  

4.    import java.awt.event.*;  

5.    import java.io.*;  

6.    import java.net.*;  

7.    import javax.swing.*;  

8.      

9.    public class SellTicket extends JFrame implements ActionListener {  

10.      public SellTicket() {  

11.          lock = true;  

12.          this.setTitle("铁路售票系统");  

13.          this.setBounds(300300300300);  

14.          this.setResizable(false);  

15.          controlButton = new JButton("开始售票");// 开始售票的按钮  

16.          controlButton.addActionListener(this);// 为按钮添加事件响应  

17.          conditionPanel = new JPanel();// 显示信息的面板  

18.          this.conditionPanel.setLayout(new GridLayout(31));// 网格布局管理器,31  

19.          conditionLabel = new JLabel("售票已停止");// 显示售票状态  

20.          personLabel = new JLabel("当前有" + personNum + "人在排队等候");// 显示当前的排队等待人数  

21.          ticketLabel = new JLabel("当前已售出" + sellNum + "张票");// 显示当前已售出多少张票  

22.          conditionPanel.add(personLabel);  

23.          conditionPanel.add(conditionLabel);  

24.          conditionPanel.add(ticketLabel);  

25.          this.add(conditionPanel, BorderLayout.CENTER);// 显示信息的面板添加到中间  

26.          this.add(controlButton, BorderLayout.SOUTH);// 售票的控制按钮添加到南边  

27.          this.addWindowListener(new WindowAdapter() {// 为关闭按钮添加事件响应  

28.              @Override  

29.              public void windowClosing(WindowEvent e) {  

30.                  try {  

31.                      ips.close();// 关闭输入流  

32.                      ops.close();// 关闭输出流  

33.                      socket.close();// 关闭与客户端创建的套接字  

34.                      serverSocket.close();// 关闭服务器端套接字  

35.                  } catch (Exception ex) {  

36.                      ex.printStackTrace();  

37.                  }  

38.                  SellTicket.this.dispose();// 释放窗口所使用的屏幕资源  

39.                  System.exit(0);// 退出程序  

40.              }  

41.    

42.          });  

43.          this.setVisible(true);  

44.          try {  

45.              serverSocket = new ServerSocket(8887);// 创建服务器套接字  

46.          } catch (IOException e1) {  

47.              e1.printStackTrace();  

48.          }  

49.          sellThread = new Thread(new Runnable() {// 创建一个线程来售票  

50.                      public void run() {  

51.                          try {  

52.                              while (true) {  

53.                                  for (int i = 0; i < sellSpeed; i++) {  

54.                                      Thread.sleep(1000);  

55.                                      if (lock) {  

56.                                          time--;  

57.                                          message = "时间"  

58.                                                  + new Integer(time).toString();  

59.                                          ops.write((new Integer(message  

60.                                                  .getBytes().length).toString() + message)  

61.                                                  .getBytes());// 发送客户端的剩余等待时间  

62.                                      } else {  

63.                                          i--;  

64.                                      }  

65.                                  }  

66.                                  personNum--;  

67.                                  sellNum++;  

68.                                  displaySellNum();  

69.                                  displayPerson();  

70.                                  message = "人数"  

71.                                          + new Integer(personNum).toString();  

72.                                  ops.write((new Integer(  

73.                                          message.getBytes().length).toString() + message)  

74.                                          .getBytes());// 发送客户端前面的等待人数  

75.                                  if (time == 0) {  

76.                                      lock = false;  

77.                                  } else {  

78.                                      lock = true;  

79.                                  }  

80.                              }  

81.                          } catch (Exception e) {  

82.                              e.printStackTrace();  

83.                          }  

84.                      }  

85.                  });  

86.          new Thread(new Runnable() {  

87.              @Override  

88.              public void run() {  

89.                  createServer();  

90.              }  

91.          }).start();  

92.      }  

93.    

94.      public static void main(String[] args) {  

95.          SellTicket sellTicket = new SellTicket();// 创建客户端  

96.      }  

97.    

98.      @Override  

99.      public void actionPerformed(ActionEvent e) {// 售票控制按钮的事件响应  

100.          try {  

101.              if (controlButton.getText().equals("开始售票")) {// 点击了开始售票按钮  

102.                  if (Thread.State.NEW == sellThread.getState()) {  

103.                      sellThread.start();  

104.                  } else {  

105.                      if (0 != time)  

106.                          lock = true;  

107.                  }  

108.                  conditionLabel.setText("售票中……");  

109.                  controlButton.setText("停止售票");  

110.              } else {  

111.                  conditionLabel.setText("售票已停止");// 点击了停止售票按钮  

112.                  controlButton.setText("开始售票");  

113.                  lock = false;  

114.              }  

115.          } catch (Exception ee) {  

116.              ee.printStackTrace();  

117.          }  

118.      }  

119.    

120.      public void displayPerson() {// 刷新当前的排队人数  

121.          personLabel.setText("当前有" + personNum + "人在排队等候");  

122.      }  

123.    

124.      public void displaySellNum() {// 刷新当前已售出的票数  

125.          ticketLabel.setText("当前已售出" + sellNum + "张票");  

126.      }  

127.    

128.      public void createServer() {  

129.          try {  

130.              socket = serverSocket.accept();// 等待客户端的访问  

131.              ips = socket.getInputStream();  

132.              ops = socket.getOutputStream();  

133.              byte[] buf = new byte[10];  

134.              int len;  

135.              String message;  

136.              while (true) {  

137.                  len = ips.read() - '0';  

138.                  if (-49 == len) {  

139.                      continue;  

140.                  } else {  

141.                      ips.read(buf, 0, len);  

142.                      message = new String(buf, 0, len);  

143.                      if (message.equals("入队")) {  

144.                          personNum++;  

145.                          time += sellSpeed;  

146.                          message = "人数" + new Integer(personNum).toString();  

147.                          ops.write((new Integer(message.getBytes().length)  

148.                                  .toString() + message).getBytes());// 向客户端发送当前的等待人数  

149.                          message = "时间" + new Integer(time).toString();  

150.                          ops.write((new Integer(message.getBytes().length)  

151.                                  .toString() + message).getBytes());// 向客户端发送剩余等待时间  

152.                      } else if (message.equals("出队")) {  

153.                          personNum--;  

154.                          time -= sellSpeed;  

155.                      }  

156.                      this.displayPerson();  

157.                      this.displaySellNum();  

158.                  }  

159.              }  

160.          } catch (Exception e) {  

161.              e.printStackTrace();  

162.          }  

163.      }  

164.    

165.      private JButton controlButton;  

166.      private JLabel conditionLabel;  

167.      private JLabel personLabel;  

168.      private JLabel ticketLabel;  

169.      private JPanel conditionPanel;  

170.      private int personNum = 10;  

171.      private int sellSpeed = 3;  

172.      private int time = personNum * sellSpeed;  

173.      private int sellNum = 0;  

174.      private InputStream ips;  

175.      private OutputStream ops;  

176.      private ServerSocket serverSocket;  

177.      private Socket socket;  

178.      private String message;  

179.      private Thread sellThread;  

180.      private boolean lock;  

181.  }  

客户端

1.    package com.itheima.bzx;  

2.      

3.    import java.awt.event.*;  

4.    import java.awt.*;  

5.    import java.io.*;  

6.    import java.net.*;  

7.    import javax.swing.*;  

8.      

9.    public class BuyTicket extends JFrame implements ActionListener {  

10.      public BuyTicket() {  

11.          this.setTitle("铁路排队购票系统");  

12.          this.setBounds(300300300300);  

13.          this.setResizable(false);  

14.          this.personLabel = new JLabel();// 显示前面还有多少人在排队  

15.          this.timeLabel = new JLabel();// 显示剩余等待时间  

16.          this.conditionPanel = new JPanel();// 显示信息的面板,它上面的组件有personLabelconditionLabeltimeLabel  

17.          conditionPanel.setLayout(new GridLayout(31));// 这个显示信息的面板,网格布局管理器,31  

18.          inLineButton = new JButton("开始排队");  

19.          inLineButton.addActionListener(this);  

20.          conditionLabel = new JLabel("未排队");// 显示客户是否已经在排队的队列中,初始为未排队  

21.          this.conditionPanel.add(personLabel);  

22.          this.conditionPanel.add(conditionLabel);  

23.          this.conditionPanel.add(timeLabel);  

24.          this.add(conditionPanel, BorderLayout.CENTER);// 将显示信息的面板加在边界布局管理器的中间  

25.          this.add(inLineButton, BorderLayout.SOUTH);// 将排除按钮加在边界布局管理器的南边  

26.          this.addWindowListener(new WindowAdapter() {// 为关闭按钮添加事件响应  

27.              @Override  

28.              public void windowClosing(WindowEvent e) {  

29.                  exit();// 退出程序  

30.              }  

31.          });  

32.          this.setVisible(true);  

33.          try {  

34.              socket = new Socket("127.0.0.1"8887);// 服务器的IP和端口号  

35.              ips = socket.getInputStream();  

36.              ops = socket.getOutputStream();  

37.          } catch (Exception e) {  

38.              e.printStackTrace();  

39.          }  

40.          new Thread(new Runnable() {  

41.              @Override  

42.              public void run() {  

43.                  getMessege();  

44.              }  

45.          }).start();// 客户端一旦被创建,就启动一个从服务器接收数据的线程  

46.      }  

47.    

48.      public static void main(String[] args) {  

49.          BuyTicket buyTicket = new BuyTicket();// 创建客户端  

50.      }  

51.    

52.      @Override  

53.      public void actionPerformed(ActionEvent e) {// 排队按钮的事件响应  

54.          if (((JButton) e.getSource()).getText().equals("开始排队")) {// 点击了开始排队按钮  

55.              conditionLabel.setText("排队中……");  

56.              inLineButton.setText("取消排队");  

57.              try {  

58.                  ops.write((new Integer("入队".getBytes().length).toString() + "入队")  

59.                          .getBytes());// 向服务器发送入队的消息  

60.              } catch (IOException e1) {  

61.                  e1.printStackTrace();  

62.              }  

63.          } else if (((JButton) e.getSource()).getText().equals("取消排队")) {// 点击了取消排队按钮  

64.              timeLabel.setText("");  

65.              personLabel.setText("");  

66.              inLineButton.setText("开始排队");  

67.              conditionLabel.setText("未排队");  

68.              try {  

69.                  ops.write((new Integer("出队".getBytes().length).toString() + "出队")  

70.                          .getBytes());// 向服务器发送出队的消息  

71.              } catch (IOException e1) {  

72.                  e1.printStackTrace();  

73.              }  

74.          } else {  

75.              exit();  

76.          }  

77.          ;  

78.      }  

79.    

80.      public void setPerson(int person) {// 设置前面还有多少人在等待  

81.          personLabel.setText("您前面还有" + (person - 1) + "人在排队等候");  

82.      }  

83.    

84.      public void setTime(int time) {// 设置还要等待多长和时间  

85.          timeLabel.setText("您还需等待" + time / 60 + "分钟" + time % 60 + "");  

86.      }  

87.    

88.      private void exit() {// 退出程序  

89.          try {  

90.              ips.close();// 关闭输入流  

91.              ops.close();// 关闭输出流  

92.              socket.close();// 关闭客户端套接字  

93.          } catch (Exception ex) {  

94.              ex.printStackTrace();  

95.          }  

96.          BuyTicket.this.dispose();// 释放窗口所使用的屏幕资源  

97.          System.exit(0);// 退出程序  

98.      }  

99.    

100.      private void getMessege() {// 从服务器端获取消息  

101.          try {  

102.              byte[] buf = new byte[20];  

103.              int len;  

104.              String message;  

105.              while (true) {  

106.                  len = ips.read() - '0';  

107.                  if (-49 == len) {// 没有读到消息继续下一次读取  

108.                      continue;  

109.                  }  

110.                  System.out.println(len);  

111.                  ips.read(buf, 0, len);  

112.                  message = new String(buf, 0, len);  

113.                  System.out.println(message);  

114.                  if (message.substring(02).equals("人数")) {// 收到的为剩余人数的消息  

115.                      this.setPerson(Integer.parseInt(message.substring(2,  

116.                              message.length())));  

117.                  } else if (message.substring(02).equals("时间")) {// 收到的为剩余时间的消息  

118.                      this.setTime(Integer.parseInt(message.substring(2,  

119.                              message.length())));  

120.                      if (message.substring(2, message.length()).equals("0")) {// 排队到了播放提示音  

121.                          JApplet.newAudioClip(  

122.                                  new File("src\\tip.wav").toURI().toURL())  

123.                                  .loop();  

124.                          this.conditionLabel.setText("轮到你了");  

125.                          this.personLabel.setText("");  

126.                          this.timeLabel.setText("");  

127.                          this.inLineButton.setText("确定");  

128.                          break;  

129.                      }  

130.                  }  

131.              }  

132.          } catch (Exception e) {  

133.              e.printStackTrace();  

134.          }  

135.      }  

136.    

137.      private JButton inLineButton;  

138.      private JLabel conditionLabel;  

139.      private JLabel personLabel;  

140.      private JLabel timeLabel;  

141.      private JPanel conditionPanel;  

142.      private InputStream ips;  

143.      private OutputStream ops;  

144.      private Socket socket;  

145.      private boolean flag = true;  

146.  }  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值