黑马程序员(十)
来源:互联网 发布:阿里云百度云差距 编辑:程序博客网 时间:2024/06/07 12:11
TCP网络通信程序设计与实现
摘要:
目前,基于TCP/IP协议的网络得到了普及和飞速的发展,Windows下的网络程序越来越显得重要。利用TCP/IP协议提供的编程接口———Socket(套接字)可以开发出TCP/IP应用程序。正确的使用WindowsSocket,就可使得不同地址下的进程得以在Windows环境下顺利进行各种网络通信,因此研究WinSock更有意义。而基于TCP/IP协议网络环境下的应用程序是通过客户机/服务器(C/S)作用方式模式在网络(应用)编程界面实现的。本次实验采用java语言设计一个基于C/S模式的TCP网络通讯程序。实现客户端与服务器端之间的数据传输。
关键词:TCP/IP 网络通信 java C/S(client/server)模式
1引言
计算机网络通信是以计算机为信息接收终端,融合了计算机网络技术的通信方式。计算机网络通信顺畅的重要保障就是网络建设。同时,网络建设也是计算机应用普及的基本条件,是推动经济社会发展的根本。因此,了解计算机网络知识及网络编程技巧对于IT技术人员是必备技术之一。
2 基础理论和技术
2.1网络基础知识
网络上的计算机要互相通信,必须遵循一定的协议。目前使用最广泛的网络协议是Internet上所使用的TCP/IP协议。
在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一地确定Internet上的一台主机。而TCP层则提供面向应用的可靠的或非可靠的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据的。
网络编程主要解决两大问题:(1)如何准确的定位网络上一台或多台主机 (2)找到主机后如何可靠高效的进行数据传输。
目前较流行的网络编程模型是客户机/服务器(C/S)结构。即通信双方一方作为服务器等待客户提出请求并予以响应。客户则在需要服务时向服务器提出申请。服务器一般作为守护进程始终运行,监听网络端口,一旦有客户请求,就会启动一个服务进程来响应该客户,同时自己继续监听服务端口,使后来的客户也能及时得到服务。
IP地址:标识计算机等网络设备的网络地址,由四个8位的二进制数组成,中间以小数点分隔。
比如166.111.136.3 , 166.111.52.80
主机名(hostname):网络地址的助记名,按照域名进行分级管理。
端口号(port number):网络通信时同一机器上的不同进程的标识。
服务类型(service):网络的各种服务。
在Internet上IP地址和主机名是一一对应的,通过域名解析可以由主机名得到机器的IP,由于机器名更接近自然语言,容易记忆,所以使用比IP地址广泛,但是对机器而言只有IP地址才是有效的标识符。
光用主机名或IP地址来标识这么多个进程显然是不够的,只有通过主机名或IP地址和端口号的组合才能唯一的确定网络通讯中的对象:进程。服务类型是那些已经被TCP/IP协议标准化的在TCP应用层上的应用,一般都是网络服务器(软件)。可以编写自己的基于网络的服务器,但都不能被称作标准的服务类型。
两类传输协议:TCP/UDP
在TCP/IP的传输层同时存在TCP和UDP两个协议。
TCP(Tranfer Control Protocol): 一种面向连接(可靠)的传输控制协议。通过TCP协议传输,得到的是一个顺序、无差错的数据流。发送方和接收方成对的两个socket之间必须建立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作。
UDP(User Datagram Protocol): 一种无连接(不可靠)的用户数据报协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。
比较TCP\Datagram:
TCP——可靠,传输大小无限制,但是需要连接建立时间,差错控制开销大。
UDP——不可靠,差错控制开销较小,传输大小限制在64K以下,不需要建立连接。
TCP虽然有诸多优点,但是也有缺点:TCP传输的效率不如UDP高,对数据内容正确性的检验要占用计算机处理时间和网络带宽,此外在许多应用中并不需要保证严格的传输可靠性,比如视频会议系统,这种情况下显然使用UDP会更合理一些。
2.2 java网络编程技术
Java语言是在网络环境下诞生的,所以Java语言虽然不能说是对于网络编程的支持最好的语言,但是必须说是一种对于网络编程提供良好支持的语言,使用Java语言进行网络编程将是一件比较轻松的工作。
2.3 Socket套接字
所谓socket通常也称作"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求。以J2SDK-1.3为例,Socket和ServerSocket类库位于java .net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。
重要的SocketAPI:java .net.Socket继承于java.lang.Object,有八个构造器,其方法并不多,下面介绍使用最频繁的三个方法,其它方法大家可以见JDK-1.3文档。
Accept方法用于产生"阻塞",直到接受到一个连接,并且返回一个客户端的Socket对象实例。"阻塞"是一个术语,它使程序运行暂时"停留"在这个地方,直到一个会话产生,然后程序继续;通常"阻塞"是由循环产生的。
getInputStream方法获得网络连接输入,同时返回一个InputStream对象实例。
getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。注意:其中getInputStream和getOutputStream方法均可能会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。
根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。
服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
3 系统功能设计
网络编程都是由客户端和服务器端组成。
一 客户端网络编程步骤
客户端(Client)是指网络编程中首先发起连接的程序,客户端一般实现程序界面和基本逻辑实现,在进行实际的客户端编程时,无论客户端复杂还是简单,以及客户端实现的方式,客户端的编程主要由三个步骤实现:
1、 建立网络连接
客户端网络编程的第一步都是建立网络连接。在建立网络连接时需要指定连接到的服务器的IP地址和端口号,建立完成以后,会形成一条虚拟的连接,后续的操作就可以通过该连接实现数据交换了。
2、 交换数据
连接建立以后,就可以通过这个连接交换数据了。交换数据严格按照请求响应模型进行,由客户端发送一个请求数据到服务器,服务器反馈一个响应数据给客户端,如果客户端不发送请求则服务器端就不响应。
根据逻辑需要,可以多次交换数据,但是还是必须遵循请求响应模型。
3、 关闭网络连接
在数据交换完成以后,关闭网络连接,释放程序占用的端口、内存等系统资源,结束网络编程。
最基本的步骤一般都是这三个步骤,在实际实现时,步骤2会出现重复,在进行代码组织时,由于网络编程是比较耗时的操作,所以一般开启专门的现场进行网络通讯。
二 服务器端网络编程步骤
服务器端(Server)是指在网络编程中被动等待连接的程序,服务器端一般实现程序的核心逻辑以及数据存储等核心功能。服务器端的编程步骤和客户端不同,是由四个步骤实现,依次是:
1、 监听端口
服务器端属于被动等待连接,所以服务器端启动以后,不需要发起连接,而只需要监听本地计算机的某个固定端口即可。
这个端口就是服务器端开放给客户端的端口,服务器端程序运行的本地计算机的IP地址就是服务器端程序的IP地址。
2、 获得连接
当客户端连接到服务器端时,服务器端就可以获得一个连接,这个连接包含客户端的信息,例如客户端IP地址等等,服务器端和客户端也通过该连接进行数据交换。
一般在服务器端编程中,当获得连接时,需要开启专门的线程处理该连接,每个连接都由独立的线程实现。
3、 交换数据
服务器端通过获得的连接进行数据交换。服务器端的数据交换步骤是首先接收客户端发送过来的数据,然后进行逻辑处理,再把处理以后的结果数据发送给客户端。简单来说,就是先接收再发送,这个和客户端的数据交换数序不同。
其实,服务器端获得的连接和客户端连接是一样的,只是数据交换的步骤不同。
当然,服务器端的数据交换也是可以多次进行的。
在数据交换完成以后,关闭和客户端的连接。
4、 关闭连接
当服务器程序关闭时,需要关闭服务器端,通过关闭服务器端使得服务器监听的端口以及占用的内存可以释放出来,实现了连接的关闭。
4 系统实现
(一)主要源代码功能分析
.客户端的Socket的创建:
try {
//当触发连接按钮时,实例化一个客户端
client=new Socket("127.0.0.1",2000);
//隐藏连接界面,显示通信界面
frame.setVisible(false);
frame1.setVisible(true);
jieshoukuang.append("已经连接上服务器!"+"\n");
} catch (IOException e1){
System.out.println("链接失败!");
e1.printStackTrace();
}
}
.服务端ServerSocket的创建:
new Server(); //生成服务器界面
//通过服务器端构造函数 ServerSocket(port) 实例化一个服务器端口
ServerSocket server=new ServerSocket(2000);
text.append("监听2000端口"+"\n");
//实例化一个接受服务器数据的对象
Socket client=server.accept();
客户端程序界面:
frame=new JFrame();
adress=new JLabel("IP 地址");
port =new JLabel("端口号");
adresstext=new JTextField("127.0.0.1",10);
porttext=new JTextField("2000",10);
connect=new JButton("连接");
//连接界面的布局
frame.setLayout(new FlowLayout());
frame.add(adress);
frame.add(adresstext);
frame.add(port);
frame.add(porttext);
frame.add(connect);
frame.setVisible(true);
frame.setSize(200,150);
connect.addActionListener(this);
//通信界面的实例化
frame1=new JFrame();
shuru=new JLabel("请输入");
shurukuang=new JTextArea("请输入····",5,40);
panel1=new JPanel();
panel1.add(shuru);
panel1.add(shurukuang);
panel1.setLayout(new FlowLayout());
send=new JButton("发送");
panel2=new JPanel();
jieshou=new JLabel("已接受");
jieshoukuang=new TextArea(8,60);
jieshoukuang.setEditable(false);
panel2.add(jieshou);
panel2.add(jieshoukuang);
panel2.setLayout(new FlowLayout());
frame1.setLayout(new FlowLayout());
//通信界面都的布局
frame1.add(BorderLayout.NORTH,panel1);
frame1.add(send);
frame1.add(BorderLayout.SOUTH,panel2);
//连接时通信界面是处于看不到的
frame1.setVisible(false);
frame1.setSize(500,350);
send.addActionListener(this);
服务器端程序界面:
public Server(){
//服务器端的界面的实例化
JFrame frame=new JFrame("服务器端");
text=new JTextArea();
JScrollPane scroll =new JScrollPane(text);
frame.add(scroll);
frame.setVisible(true);
frame.setSize(300,400);
//这里设置服务器端的文本框是不可编辑的
text.setEditable(false);
}
- 黑马程序员(十)
- 黑马程序员 日记(十)
- 黑马程序员 学习日记(十)
- 黑马程序员 学习日记(十)
- 【黑马程序员】网络编程(十)
- 黑马程序员——(十)反射
- 黑马程序员-- 十、IO
- 黑马程序员_笔记十
- “黑马程序员”学习笔记十
- 黑马程序员-------.net基础知识十
- 黑马程序员-----笔记整理(java基础十----集合)
- 黑马程序员-----java基础十(java之异常)
- 黑马程序员--交通灯管理系统(二十)
- 黑马程序员《java基础总结(十)》(泛型、API)
- 黑马程序员-第二十一天(Properties类)
- 【黑马程序员】C语言学习笔记之字符串(十)
- 黑马程序员-第二十三天(字符编码)
- 黑马程序员-第二十三天(字符编码)
- java 实现输入一个字符串,打印出其中所有的数字
- python decorator(装饰器)
- vrml文件的使用
- 旋转卡壳:cdoj942
- java调用c++
- 黑马程序员(十)
- 鼠标屏幕取词技术的原理和实现
- HTML5 postMessage 和 onmessage API 详细应用
- 第二次使用回调
- 理解Bellman Equation
- Ubuntu 12.04下安装Oracle Express 11gR2
- EF:插入记录失败,提示当 IDENTITY_INSERT 设置为 OFF 时,不能向表中的标识列插入显式值
- 2:约瑟夫问题
- ubuntu中启动oracle数据库