此文章写于2021年6月29日

一.背景概述
TCP(传输控制协议)是一种面向连接的,可靠的传输层协议。TCP协议在网络层IP协议的基础上,向应用层用户进程提供可靠的,全双工的数据流传输。

二.设计内容
本课程设计的目的就是设计一个发送TCP数据包的程序,并根据本设计说明TCP数据包的结构以及TCP协议与IP协议的关系,使学生对TCP协议的工作原理有更深入的认识。

三.设计要求
本课程的功能是填充一个TCP数据包,并发送给目的主机。
(1)推荐采用图形界面实现。
(2)程序代码书写规范,有充足的注释。
(3)程序运行:填写目的IP,目的端口。
(4)开发平台、开发语言不限。
(5)明确题目的意图,设计上应有足够的工作量。
(6)成功发送后在屏幕上输出“Send OK”。

四.总体设计
程序的实现由三部分组成:表示层,工具层和应用层
(1)在表示层上,主要是程序与用户交互界面的实现
(2)在工具层上,主要是对应用层中所用到的技术进行封装,以便于调用,并使代码易读。
(3)在应用层上,主要是对TCP数据包进行发送和接收。

程序流程图

设计思路
首先创建一个接收端用于监听用户指定的端口,如果在指定的端口获取到信息,就将其输出到文本框当中;在发送端,程序根据用户输入的目的IP,目的端口和需要发送的消息,创建一个TCP数据包,发送出去。

设计环境
IntelliJ IDEA 2020.2,Windows 10

基本功能
我设计的TCP数据包发送端有以下几个功能

  1. 当用户填写的表单不全时,会进行提示
  2. 根据用户填写的IP和端口号发送TCP数据包。

TCP数据包接收端有以下几个功能

  1. 当用户填写的表单不全时,会进行提示
  2. 监听用户填写的端口号

详细设计
发送端:
某些变量的定义:

String destIp;//用户输入的目的IP
String destPort;//用户输入的目的端口
String msg;//用户输入的需要发送的信息
Socket socket;//套接字对象
Sender main;//发送端主窗口

socketUtil工具类:
负责创建Socket对象和关闭Socket对象的工具类,
此类中的getSocket方法通过用户输入的ip和端口号获取socket对象;
close方法将传入的socket对象进行关闭。

public class socketUtil {  private socketUtil(){}  /** * 关闭socket和serverSocket * @param sk */  public static void close(Socket sk){  try {  sk.close();  } catch (Exception ex) {  ex.printStackTrace();  }  }  /** * 获取Socket对象 * @param ip * @param port * @return */  public static Socket getSocket(String ip,int port) throws IOException {  Socket socketObj = new Socket(ip,port);  return socketObj;  }
} 

stringUtil工具类:
主要用于判断字符串是否为空

public class stringUtil {  /** * 判断字符串是否为空 * @param str * @return */  public static boolean isEmpty(String str){  if(str==null || "".equals((str.trim()))){  return true;  }  else{  return false;  }  }  } 

在Sender类中初始化发送端主界面的函数:
主要组件有ip输入框,端口输入框,消息输入框和一个发送按钮。

private void initComponents() {  // JFormDesigner - Component initialization - DO NOT MODIFY  //GEN-BEGIN:initComponents  ResourceBundle bundle = ResourceBundle.getBundle("logInFrm");  label1 = new JLabel();  label2 = new JLabel();  socketIpTxt = new JTextField();  socketPortTxt = new JTextField();  scrollPane1 = new JScrollPane();  messageTxt = new JTextArea();  label3 = new JLabel();  button1 = new JButton();  //======== this ========  setTitle(bundle.getString("Sender.this.title"));  setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);  Container contentPane = getContentPane();  //---- label1 ----  label1.setText(bundle.getString("Sender.label1.text"));  //---- label2 ----  label2.setText(bundle.getString("Sender.label2.text"));  //======== scrollPane1 ========  {  scrollPane1.setViewportView(messageTxt);  }  //---- label3 ----  label3.setText(bundle.getString("Sender.label3.text"));  //---- button1 ----  button1.setText(bundle.getString("Sender.button1.text"));  button1.addActionListener(e -> button1ActionPerformed(e));  GroupLayout contentPaneLayout = new GroupLayout(contentPane);  contentPane.setLayout(contentPaneLayout);  contentPaneLayout.setHorizontalGroup(  contentPaneLayout.createParallelGroup()  .addGroup(contentPaneLayout.createSequentialGroup()  .addContainerGap(83, Short.MAX_VALUE)  .addGroup(contentPaneLayout.createParallelGroup()  .addComponent(label2, GroupLayout.Alignment.TRAILING)  .addComponent(label1, GroupLayout.Alignment.TRAILING)  .addComponent(label3, GroupLayout.Alignment.TRAILING))  .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)  .addGroup(contentPaneLayout.createParallelGroup()  .addComponent(button1)  .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.LEADING, false)  .addComponent(socketIpTxt, GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE)  .addComponent(socketPortTxt, GroupLayout.PREFERRED_SIZE, 58, GroupLayout.PREFERRED_SIZE)  .addComponent(scrollPane1, GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE)))  .addContainerGap(95, Short.MAX_VALUE))  );  contentPaneLayout.setVerticalGroup(  contentPaneLayout.createParallelGroup()  .addGroup(contentPaneLayout.createSequentialGroup()  .addGap(31, 31, 31)  .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.TRAILING)  .addComponent(label1, GroupLayout.PREFERRED_SIZE, 26, GroupLayout.PREFERRED_SIZE)  .addComponent(socketIpTxt, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))  .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)  .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)  .addComponent(label2, GroupLayout.PREFERRED_SIZE, 26, GroupLayout.PREFERRED_SIZE)  .addComponent(socketPortTxt, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))  .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)  .addGroup(contentPaneLayout.createParallelGroup()  .addComponent(scrollPane1, GroupLayout.PREFERRED_SIZE, 112, GroupLayout.PREFERRED_SIZE)  .addComponent(label3))  .addGap(18, 18, 18)  .addComponent(button1)  .addContainerGap(16, Short.MAX_VALUE))  );  pack();  setLocationRelativeTo(getOwner());  // JFormDesigner - End of component initialization  //GEN-END:initComponents  }  // JFormDesigner - Variables declaration - DO NOT MODIFY  //GEN-BEGIN:variables  private JLabel label1;  private JLabel label2;  private JTextField socketIpTxt;  private JTextField socketPortTxt;  private JScrollPane scrollPane1;  private JTextArea messageTxt;  private JLabel label3;  private JButton button1;  // JFormDesigner - End of variables declaration  //GEN-END:variables
}

在Sender类中用于执行发送TCP数据包的按钮事件监听方法:
当用户按下此按钮时,程序通过各个输入框的getText()方法获取相应的字符串并赋值给字符串对象,程序会首先判断用户输入的表单是否全面;
如果全面的话,就会通过输入的ip和端口号创建一个socket对象;
随后会通过socket对象的getOutPueStream方法创建一个outPutStream对象,并在此基础上创建一个outPutStreamWriter对象;
之后利用outPutStreamWriter对象的write方法将msg消息字符串发送到输出流,并进行刷新;
发送完成后,通过调用socket对象的close方法关闭socket,并提示消息框:“Send OK!”。

private void button1ActionPerformed(ActionEvent e) {  String destIp = this.socketIpTxt.getText();  String destPort = this.socketPortTxt.getText();  String msg = this.messageTxt.getText();  Socket socketObj = null;  /** * 参数数量不正确 */  if(stringUtil.isEmpty(destIp)) {  JOptionPane.showMessageDialog(null,"请输入IP!");  return;  }  if(stringUtil.isEmpty(destPort)) {  JOptionPane.showMessageDialog(null,"请输入端口号!");  return;  }  if(stringUtil.isEmpty(msg)) {  JOptionPane.showMessageDialog(null,"请输入要发送的消息!");  return;  }  try {  /** * 创建socket对象 */  String str = msg;  socketObj = new Socket(destIp,Integer.parseInt(destPort));  /** * 创建OutStreamWriter对象 */  OutputStream os = socketObj.getOutputStream();  OutputStreamWriter osw = new OutputStreamWriter(os);  osw.write(str);//输出字符流  osw.flush();  socketUtil.close(socketObj);  JOptionPane.showMessageDialog(null,"Send OK!");  } catch(Exception ex) {  JOptionPane.showMessageDialog(null,"Sorry,can’t connect to "+destIp+":"+destPort);  ex.printStackTrace();  }
}  

当用户没有输入目的IP或者目的端口或者消息时,图形界面会分别弹出消息框提示用户:



mainSender类中用于实例化窗口的主方法:

public static void main(String[] args) {  Sender main = new Sender();  main.setBounds(300,300,500,330);  main.setVisible(true);
}


接收端:
接收端某些变量的定义:

SeverSocket severSocket;//负责接收发送端连接请求的SeverSocket
Socket socket;//severSocket的accept方法获取的Socket对象
String port;//用户输入的端口号
Reveiver main;//接收端主窗口

socketUtil工具类:
主要包含用于获取serverSocket对象和关闭socket对象的方法。
getServerSocket方法利用用户输入的端口号,创建一个severSocket对象。
close方法将传入的socket对象和severSocket对象进行关闭。

public class socketUtil {  private socketUtil(){}  /** * 获取serverSocket对象 * @param port * @return serverSocket * @throws Exception */  public static ServerSocket getServerSocket(int port) throws Exception{  ServerSocket serverSocket= new ServerSocket( Integer.valueOf(port) );  return serverSocket;  }  /** * 关闭socket和serverSocket * @param sk * @param ss */  public static void close(Socket sk, ServerSocket ss){  try {  ss.close();  sk.close();  } catch (IOException ex) {  ex.printStackTrace();  }  }  public static void close(Socket sk){  try {  sk.close();  } catch (Exception ex) {  ex.printStackTrace();  }  }
}  

stringUtil工具类:
主要用于判断字符串是否为空。

public class stringUtil {  /** * 判断字符串是否为空 * @param str * @return */  public static boolean isEmpty(String str){  if(str==null || "".equals((str.trim()))){  return true;  }  else{  return false;  }  }  }  

Reciver类中的初始化接收端窗口的方法:
主要组件包括:一个端口输入框,一个消息展示框和一个监听按钮。

private void initComponents() {  // JFormDesigner - Component initialization - DO NOT MODIFY  //GEN-BEGIN:initComponents  ResourceBundle bundle = ResourceBundle.getBundle("logInFrm");  button1 = new JButton();  receiverMsgTxt = new JTextArea();  label2 = new JLabel();  portTxt = new JTextField();  label1 = new JLabel();  //======== this ========  setTitle("Receiver");  setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);  Container contentPane = getContentPane();  //---- button1 ----  button1.setText(bundle.getString("demo.button1.text"));  button1.addActionListener(e -> button1ActionPerformed(e));  //---- label2 ----  label2.setText(bundle.getString("demo.label2.text"));  //---- label1 ----  label1.setText(bundle.getString("demo.label1.text"));  GroupLayout contentPaneLayout = new GroupLayout(contentPane);  contentPane.setLayout(contentPaneLayout);  contentPaneLayout.setHorizontalGroup(  contentPaneLayout.createParallelGroup()  .addGroup(contentPaneLayout.createSequentialGroup()  .addGap(42, 42, 42)  .addGroup(contentPaneLayout.createParallelGroup()  .addGroup(contentPaneLayout.createSequentialGroup()  .addGap(35, 35, 35)  .addComponent(label1)  .addGap(2, 2, 2)  .addComponent(portTxt, GroupLayout.PREFERRED_SIZE, 87, GroupLayout.PREFERRED_SIZE))  .addGroup(contentPaneLayout.createSequentialGroup()  .addGap(57, 57, 57)  .addComponent(label2))  .addComponent(receiverMsgTxt, GroupLayout.PREFERRED_SIZE, 207, GroupLayout.PREFERRED_SIZE)  .addGroup(contentPaneLayout.createSequentialGroup()  .addGap(62, 62, 62)  .addComponent(button1)))  .addContainerGap(89, Short.MAX_VALUE))  );  contentPaneLayout.setVerticalGroup(  contentPaneLayout.createParallelGroup()  .addGroup(contentPaneLayout.createSequentialGroup()  .addGap(26, 26, 26)  .addGroup(contentPaneLayout.createParallelGroup()  .addGroup(contentPaneLayout.createSequentialGroup()  .addGap(3, 3, 3)  .addComponent(label1))  .addComponent(portTxt, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))  .addGap(18, 18, 18)  .addComponent(label2)  .addGap(7, 7, 7)  .addComponent(receiverMsgTxt, GroupLayout.PREFERRED_SIZE, 118, GroupLayout.PREFERRED_SIZE)  .addGap(7, 7, 7)  .addComponent(button1)  .addContainerGap(33, Short.MAX_VALUE))  );  pack();  setLocationRelativeTo(getOwner());  // JFormDesigner - End of component initialization  //GEN-END:initComponents  }  // JFormDesigner - Variables declaration - DO NOT MODIFY  //GEN-BEGIN:variables  private JButton button1;  private JTextArea receiverMsgTxt;  private JLabel label2;  private JTextField portTxt;  private JLabel label1;  // JFormDesigner - End of variables declaration  //GEN-END:variables
} 

Reciver类中用于处理监听按钮事件的方法:
主要用于监听用户输入的端口号。
程序开始的时候,会将图形界面中端口输入框的getText方法将字符串读取出来保存到新创建的字符串对象中,如果端口输入框为空,会弹出消息框提醒用户输入端口号;
如果输入了端口号,程序或通过socketUtil工具类的getSeverSocket方法并结合用户输入的端口号获取一个severSocket对象,并发送一个消息框:“监听中…”;
之后,程序会利用severSocket的accept方法获取一个socket对象,并利用socket对象的getInputStream方法获取一个inPutStream对象;
随后程序会调用inPutStream对象的read方法将输入流的字符串读入并进行刷新,并将其设置为消息展示框的内容;
最后程序会调用socketUtil工具类的close方法将socket对象和severSocket对象进行关闭。

private void button1ActionPerformed(ActionEvent e) {  ServerSocket serverSocket=null;  Socket socket = null;  String port = this.portTxt.getText();  if(stringUtil.isEmpty(port)){  JOptionPane.showMessageDialog(null,"请输入端口号!");  return;  }  try {  //构造ServerSocket实例,指定端口监听客户端的连接请求  serverSocket = socketUtil.getServerSocket(Integer.valueOf(port));  JOptionPane.showMessageDialog(null,"监听中...");  //建立跟客户端的连接  socket = serverSocket.accept();  //返回此套接字的输入流  InputStream is = socket.getInputStream();  byte [] b = new   byte [ 1024 ];  is.read(b);  if(b != null){  JOptionPane.showMessageDialog(null,"成功监听到消息!");  }  String receiverMsgStr = new  String (b);  this.receiverMsgTxt.setText(receiverMsgStr);  } catch (Exception ex) {  ex.printStackTrace();  } finally {  //操作结束,关闭socket  socketUtil.close(socket,serverSocket);  }  }

在此方法中,如果用户没有输入端口号,图形界面会创建一个消息框提示用户:

mainSender类中用于实例化接收窗口的方法:

1.   public static void main(String[] args) {
2.      Receiver main = new Receiver();
3.      main.setBounds(300,300,300,300);
4.      main.setVisible(true);
5.  }

用户通过点击“监听消息”按钮,开始对指定端口进行监听:

当接收端接收到消息以后,接收端界面中的文本框中出现接收到的消息:
五.总结与体会
在这次计算机网络课程设计的过程中,我遇到了不少的问题,例如Swing图形界面的建立,按钮事件的处理,Socket类的使用等等。在此之前我没有接触过这些,但在这次计算机网络设计过程中,我通过查阅视频,文献,资料或者与同学交流,学到了很多东西!
通过这次计算机网络课程设计,我感觉到我自己知识的欠缺,以后要学习的东西还是很多,比如网络编程,JavaWeb等等。这学期我也曾感觉到迷茫,但是在这个期末,我通过写很多代码,用到的都是刚刚学到的比较实用的知识,我感觉到我自己还是有潜力的,我也因此找到了我真正热爱的发展方向。
在这个课程设计的过程中,我也和很多同学进行了交流,感觉到了自己与他们之间的差距,也认识到了自己的优点和缺点。特别是在与同学交流的过程中我对学习过的知识进行了又一遍的复习,巩固了基础,也学习到了一些以前没有接触过的内容,除此之外,还增进了同学们之间的的友谊。
虽然这次课程设计结束了,但是我的学习之路还远远不会止步于此,我将在今后的学习生活中,严格要求自己,努力学习知识,努力完成各项试验,多进行实践,争取成为一名优秀的计算机专业学生!

六.参考文献
[1]Tamara Dean 著. 陶华敏,韩存兵,宋德伟译.计算机网络实用教程.机械工业
出版社.2000
[2] 谢希仁.《计算机网络(第 4 版)》电子工业出版社
[3] Andrew S.Tanenbaum、David J.Wetherall. 计算机网络(英文版•第 5 版). 机械工业出版社
[4] 王勇. 计算机网络课程设计(计算机课程设计与综合实践规划教材). 清华
大学出版社

计算机网络课程设计:发送TCP数据包相关推荐

  1. 【计算机网络课程设计】TCP协议包自动生成工具【蒙混过关版】

    文章目录 引言 设计要求 分工安排 文献查阅 总体设计流程 具体设计内容

  2. 计算机网络课程设计——发送和接收TCP数据包以及发送和捕获ARP数据包

    1.课程设计要求: 发送和接收TCP数据包:TCP是一种面向连接的.可靠的传输层协议.TCP协议工作在网络层IP协议的基础上.本课程设计的目的是设计一个发送和接收TCP数据包的程序,其功能是填充一个T ...

  3. 计算机网络抓包参考文献,计算机网络课程设计二(网络抓包与分析)

    <计算机网络课程设计二(网络抓包与分析)>由会员分享,可在线阅读,更多相关<计算机网络课程设计二(网络抓包与分析)(9页珍藏版)>请在人人文库网上搜索. 1.课程设计课程名称: ...

  4. 网络编程—使用C语言实现发送TCP数据包,以命令行形式运行:SendTCP source_ip source_port dest_ip dest_port;(原理和常见错误分析)

    任务要求: 1.以命令行形式运行:SendTCP source_ip source_port dest_ip dest_port: 2.头部参数自行设定,数据字段为"This is my h ...

  5. 计算机网络课程设计--基于TCP协议网上聊天程序--python实现带图形界面--socket--多线程

                                              基于TCP协议网上聊天程序 引言 21世纪是一个以网络为核心的信息时代,要实现信息化,就必须依靠完善的网络.而随着计 ...

  6. 计算机网络ip数据包分析题,计算机网络课程设计-IP数据包解析实验报告

    计算机网络课程设计-IP数据包解析实验报告 解析 IP数据报实验报告目录目录 21.课程设计目的 .22.课程设计要求 .23.相关知识 .24.课程设计分析 .64.1 网卡设置64.2 使用套接字 ...

  7. 计算机网络ip数据包分析题,计算机网络课程设计_IP数据包的捕获及分析.doc

    CENTRAL SOUTH UNIVERSITY 计算机网络课程设计报告 目录 第一章 课程设计的目的与要求1 1.1 课程设计的目的1 1.2 课程设计的要求1 第二章 课程设计的内容3 2.1 课 ...

  8. 计算机网络课程设计,使用MFC实现界面化创建ARP发送与接受程序(一)

    计算机网络课程设计,使用MFC实现界面化创建ARP发送与接受程序(一) 1.实验内容: 利用WinpCap开源库函数,编写程序实现ARP报文的发送和接收 2.实验要求: 利用WINPCAP给出的API ...

  9. TCP数据包发送的过程及实际问题解决 判断socket是否断开 解决socket数据传输数据丢失的问题

    文章目录 一.头条之问题引出 二.tcp发送数据过程 三.我的问题解决(判断socket是否断开) 四.头条之问题回答 这是篇文章是在看了今日头条后,回想起来自己曾今遇到过的一个关于socket套接字 ...

最新文章

  1. java求一个数的阶乘_Java如何使用方法计算一个数字的阶乘值?
  2. 洛谷 - P4755 Beautiful Pair(笛卡尔树+主席树)
  3. 在 iOS创建 第一个Cordova 项目
  4. SAP CRM customer classfication debug
  5. python函数调用自身后果_python 写函数在一定条件下需要调用自身时的写法说明...
  6. js面向对象编程:命名空间
  7. HDUOJ----4504 威威猫系列故事——篮球梦
  8. MyBatis返回结果不稳定
  9. android自定义View之仿携程首页点击缩放ImageView
  10. SortedList 用法
  11. windows虚拟显示器开发(三)USB显示器
  12. javascript中的逻辑运算符优先级
  13. elcom协议_物联网@电力系统通信协议
  14. pytest之.pytest_cache文件夹作用【Pytest中的cache缓存功能】
  15. linked list C++实现
  16. 《演说之禅》读书笔记
  17. 等保2.0.第十一章.等保2.0实战(上)
  18. Java Lambda(语言篇——lambda,方法引用,目标类型,默认方法,函数接口,变量捕获)
  19. AWS解决方案架构师薪资平均159,033 美元
  20. win10如何删除microsoft账户并免密登录

热门文章

  1. Android一种字幕效果的实现
  2. Android 实现图片轮播(仿淘宝首页商品轮播展示)
  3. miniconda envs目录为空
  4. OSI参考模型 TCP/IP协议族 数据封装与解封过程
  5. SNMP Android
  6. 荣耀7i android版本,荣耀7i有几个版本 荣耀7i四大版本区别
  7. 盗卖Vista可激活密钥现身北京 叫价最低50元
  8. ubuntu安装腾达(Tenda) U9网卡驱动
  9. lua 游戏开发(传送)传送阵实例
  10. 服务器销售模式,页游营销新模式:开设名人专属服务器