- 浏览: 747103 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
lengzl:
请问,那个Node 是哪个包里面的类?
JAVA 二叉树的递归和非递归遍历 -
gongchuangsu:
总结的很好,感谢感谢
JAVA 二叉树的递归和非递归遍历 -
Caelebs:
666666666 居然是10年发的,难怪截屏自动保存的名字是 ...
截图工具 -
jijiqw:
是注解不是注释。。。
Spring @Transactional (一) -
letueo:
[b][b][b][b][b][b][b][b][b][b][ ...
Spring @Transactional (一)
引用
JButton sendButton; //"发送"按钮
JTextField inputField; // 输入框
JTextArea outputAera; // 服务器返回框
public javaClient() //在建构函数中完成图形界面的初始化
{
inputField=new JTextField("这里输入..."); //供客户端输入的文本框
outputArea=new JTextArea("服务器返回"); //显示服务器返回数据的文本域
sendButton=new JButton("发送");
JPanel panel=new JPanel(); //新建面板
panel.setLayout(new BorderLayout()); //设置面板风格为BorderLayout
panel.add(inputField,BorderLayout.NORTH); //放置控件
panel.add(outputArea,BorderLayout.CENTER);
setTitle("Java通讯客户端");
setContentPane(panel);
}
}
二、 客户端通讯类clientAgent
新建一个自定义包clientAgent,包含类clientAgent,该类用来执行和服务器端的交互,将界面和通讯类分开可以使程序的调试和维护更为容易。clientAgent类的作用包括:
1、在建构函数中建立和服务器的连接。
2、sendRequest()方法向服务器发送数据。
3、getResponse()方法从服务器端获得回应
1、 成员变量
clientAgent类的成员变量包括:
PrintStream ops; //输出流(指向服务器)
DataInputStream ips;//输入流(来自服务器)
String cltRequest;//客户端请求
String svrResponse;//服务器端回应
2、 建构函数clientAgent(String serverName,int port)包含两个参数,接收从javaClient的main()函数中传递来的服务器名称和端口号
public clientAgent(String serverName,int port)
{
try
{
Socket clientSocket=new Socket(serverName,port ); //根据服务器名和端口号建立Socket
ops=new PrintStream(clientSocket.getOutputStream());//获得Socket的输出流
ips=new DataInputStream(clientSocket.getInputStream());//获得Socket的输入流
}
catch(Exception e)
{
System.out.println("无法连接服务器!");
}
}
3、 sendRequest()方法
public void sendRequest(String request)
{
ops.println(request); //向Socket的输出流写入字符串
}
4、 getRespone()方法
public String getResponse()
{
String str=new String();
try
{
str=ips.readLine(); //从Socket的输入流读入字符串
}
catch(IOException e){} //必须捕获错误
return str;
}
三、 客户端javaClient类的main()函数和事件处理
1、 main()函数
有了上面的铺垫,main()函数变得非常简洁
public static void main(String[] args)
{
javaClient frame=new javaClient();
frame.pack();//注意javaClient是JFrame的派生类,调用基类方法
frame.setVisible(true);
ca=new clientAgent("127.0.0.1",1001); //传递服务器名称和端口号
}
2、 捕获并处理单击"发送"按钮的事件
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==sendButton) //判断事件源控件是否是"发送"按钮
{
ca.sendRequest(inputField.getText()); //发送文本框中的文本
outputArea.append("\n"+ca.getResponse()); //接收服务器回应并写入文本域
}
}
四、 服务器端
1、 serverAgent类
1) 成员变量
ServerSocket svrSkt=null;
Socket cltSkt=null;
DataInputStream input=null; //输入流,来自客户端
PrintStream output=null; //输出流,指向客户端
2) serverAgent()建构函数
public serverAgent(int port) //main()函数传递监听端口号
{
System.out.println("服务器代理正在监听,端口:"+port);
try
{
svrSkt=new ServerSocket(port); //开始监听
}catch(IOException e){System.out.println("监听端口"+port+"失败");}
try
{
cltSkt=svrSkt.accept(); //接收连接请求
}
catch(IOException e){System.out.println("连接失败");}
try
{
input=new DataInputStream(cltSkt.getInputStream()); //获得输入流
output=new PrintStream(cltSkt.getOutputStream()); //获得输出流
}
catch(IOException e){}
output.println("欢迎......");
}
3) getRequest()方法读取客户端发送的数据
public String getRequest()
{
String frmClt=null;
try
{
frmClt=input.readLine();
}
catch(Exception e){
System.out.println("无法读取端口.....");
System.exit(0);
}
return frmClt;
}
4) sendResponse()方法向客户端发送数据
public void sendResponse(String response)
{
try
{
output.println(response);
}
catch(Exception e){
System.out.println("写端口失败......");
System.exit(0);
}
}
2、main()函数
在main()函数中对客户端发送的不同请求进行不同的处理,本例只是介绍原理,因此服务器端只是简单地将客户端发送来的数据发送回去:
public static void main(String[] args) throws IOException
{
serverAgent sa=new serverAgent(1001);
while(true)
{
sa.sendResponse(sa.getRequest());
}
} 更多文章 更多内容请看Java编程开发手册 Java环境安装配置专题,或进入讨论组讨论。
事实上网络编程简单的理解就是两台计算机相互通讯数据而已,对于程序员而言,去掌握一种编程接口并使用一种编程模型相对就会显得简单的多了,Java SDK提供一些相对简单的Api来完成这些工作。Socket就是其中之一,对于Java而言,这些Api存在与java.net 这个包里面,因此只要导入这个包就可以准备网络编程了。
网络编程的基本模型就是客户机到服务器模型,简单的说就是两个进程之间相互通讯,然后其中一个必须提供一个固定的位置,而另一个则只需要知道这个固定的位置。并去建立两者之间的联系,然后完成数据的通讯就可以了,这里提供固定位置的通常称为服务器,而建立联系的通常叫做客户端,基于这个简单的模型,就可以进入网络编程啦。
Java对这个模型的支持有很多种Api,而这里我只想介绍有关Socket的编程接口,对于Java而言已经简化了Socket的编程接口。首先我们来讨论有关提供固定位置的服务方是如何建立的。Java提供了ServerSocket来对其进行支持.事实上当你创建该类的一个实力对象并提供一个端口资源你就建立了一个固定位置可以让其他计算机来访问你,ServerSocket server=new ServerSocket(6789);这里稍微要注意的是端口的分配必须是唯一的。因为端口是为了唯一标识每台计算机唯一服务的,另外端口号是从 0~65535之间的,前1024个端口已经被Tcp/Ip 作为保留端口,因此你所分配的端口只能是1024个之后的。好了,我们有了固定位置.现在所需要的就是一根连接线了.该连接线由客户方首先提出要求。因此 Java同样提供了一个Socket对象来对其进行支持,只要客户方创建一个Socket的实例对象进行支持就可以了。Socket client=new Socket(InetAddress.getLocalHost(),5678);客户机必须知道有关服务器的IP地址,对于着一点Java也提供了一个相关的类InetAddress 该对象的实例必须通过它的静态方法来提供,它的静态方法主要提供了得到本机IP 和通过名字或IP直接得到InetAddress的方法。
上面的方法基本可以建立一条连线让两台计算机相互交流了,可是数据是如何传输的呢?事实上I/O操作总是和网络编程息息相关的。因为底层的网络是继续数据的,除非远程调用,处理问题的核心在执行上,否则数据的交互还是依赖于 IO操作的,所以你也必须导入java.io这个包.java的IO操作也不复杂,它提供了针对于字节流和Unicode的读者和写者,然后也提供了一个缓冲用于数据的读写。
BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));
PrintWriter out=new PrintWriter(server.getOutputStream());
上面两句就是建立缓冲并把原始的字节流转变为Unicode可以操作,而原始的字节流来源于Socket的两个方法,getInputStream()和getOutputStream()方,分别用来得到输入和输出,那么现在有了基本的模型和基本的操作工具,我们可以做一个简单的Socket例程了。
服务方:
import java.io.*;
import java.net.*;
public class MyServer {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678);
Socket client=server.accept();
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
while(true){
String str=in.readLine();
System.out.println(str);
out.println("has receive....");
out.flush();
if(str.equals("end"))
break;
}
client.close();
}
}
这个程序的主要目的在于服务器不断接收客户机所写入的信息只到,客户机发送"End"字符串就退出程序,并且服务器也会做出"Receive"为回应,告知客户机已接收到消息。
客户机代码:
import java.net.*;
import java.io.*;
public class Client{
static Socket server;
public static void main(String[] args)throws Exception{
server=new Socket(InetAddress.getLocalHost(),5678);
BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));
PrintWriter out=new PrintWriter(server.getOutputStream());
BufferedReader wt=new BufferedReader(new InputStreamReader(System.in));
while(true){
String str=wt.readLine();
out.println(str);
out.flush();
if(str.equals("end")){
break;
}
System.out.println(in.readLine());
}
server.close();
}
}
客户机代码则是接受客户键盘输入,并把该信息输出,然后输出"End"用来做退出标识。
这个程序只是简单的两台计算机之间的通讯,如果是多个客户同时访问一个服务器呢?你可以试着再运行一个客户端,结果是会抛出异常的。那么多个客户端如何实现呢?
其实,简单的分析一下,就可以看出客户和服务通讯的主要通道就是Socket本身,而服务器通过accept方法就是同意和客户建立通讯.这样当客户建立Socket的同时。服务器也会使用这一根连线来先后通讯,那么既然如此只要我们存在多条连线就可以了。那么我们的程序可以变为如下:
服务器:
import java.io.*;
import java.net.*;
public class MyServer {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678);
while(true){
Socket client=server.accept();
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
while(true){
String str=in.readLine();
System.out.println(str);
out.println("has receive....");
out.flush();
if(str.equals("end"))
break;
}
client.close();
}
}
}
这里仅仅只是加了一个外层的While循环,这个循环的目的就是当一个客户进来就为它分配一个Socket直到这个客户完成一次和服务器的交互,这里也就是接受到客户的"End"消息.那么现在就实现了多客户之间的交互了。但是.问题又来了,这样做虽然解决了多客户,可是是排队执行的。也就是说当一个客户和服务器完成一次通讯之后下一个客户才可以进来和服务器交互,无法做到同时服务,那么要如何才能同时达到既能相互之间交流又能同时交流呢?很显然这是一个并行执行的问题了。所以线程是最好的解决方案。
那么下面的问题是如何使用线程.首先要做的事情是创建线程并使得其可以和网络连线取得联系。然后由线程来执行刚才的操作,要创建线程要么直接继承Thread要么实现Runnable接口,要建立和Socket的联系只要传递引用就可以了.而要执行线程就必须重写run方法,而run方法所做的事情就是刚才单线程版本main所做的事情,因此我们的程序变成了这样:
import java.net.*;
import java.io.*;
public class MultiUser extends Thread{
private Socket client;
public MultiUser(Socket c){
this.client=c;
}
public void run(){
try{
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
//Mutil User but can parallel
while(true){
String str=in.readLine();
System.out.println(str);
out.println("has receive....");
out.flush();
if(str.equals("end"))
break;
}
client.close();
}catch(IOException ex){
}finally{
}
}
public static void main(String[] args)throws IOException{
ServerSocket server=new ServerSocket(5678);
while(true){
//transfer location change Single User or Multi User
MultiUser mu=new MultiUser(server.accept());
mu.start();
}
}
}
我的类直接从Thread类继承了下来.并且通过构造函数传递引用和客户Socket建立了联系,这样每个线程就有了。一个通讯管道.同样我们可以填写run方法,把之前的操作交给线程来完成,这样多客户并行的Socket就建立起来了。
以上的代码使用的是
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
还有一种方法是使用
DataInputStream isFromClient = new DataInputStream(client.getInputStream());
DataOutputStream osToClient = new DataOutputStream(client.getOutputStream());
关于这两种输入输出流的不同,我也只知道前一种对字符串支持比较好,后面对于读取一个字符串需要处理,但是可以支持很多种类型的输出。对于传递字符串而言前一种应该是很好的选择了。
发表评论
-
Servlet上传文件
2012-02-07 23:58 1493准备工作:要到http://commons.apache.or ... -
成为Java高手需要达到的25个学习目标--经典
2012-01-29 16:07 1351本文将告诉你学习Java需 ... -
Timer, Quartz 和 Spring 实现作业调度
2011-11-28 15:43 1175一、java.util.Timer ... -
Java 产生不重复的随机数
2011-06-22 23:32 2361int numberCount = 6; ... -
Date类学习总结(Calendar Date 字符串 相互转换 格式化)
2011-06-20 16:12 1663Date类学习总结 1.计算某一月份的最大天数 ... -
jsp中的cookie用法小实例
2011-06-20 00:13 2492这个小实例有三个页面 index.jsp页面内容如下: Y ... -
JS实现简单的增删改查
2011-06-19 23:41 12962<%@ page language="ja ... -
Jsp 动态显示系统时间
2011-06-19 23:24 4899<%@ page language=" ... -
java 动态显示时间
2011-06-19 23:13 4060import java.util.Date; p ... -
js 动态显示时间
2011-06-19 22:53 1833<%@ page language=" ... -
HTML 显示系统时间
2011-06-19 22:13 7888代码1:(显示静态时间) <script type=& ... -
JavaScript 动态显示系统时间
2011-06-19 19:36 2081JavaScript 动态显示系统时间 <html ... -
两例JavaScript 获取当前系统日期和时间
2011-06-19 19:20 1252两例JavaScript 获取当前系统日期和时间 QUOTE ... -
java五种JSP页面跳转方法详解
2011-06-19 17:08 14771. RequestDispatcher.forward() ... -
Java Object方法
2011-06-19 16:47 1356package com.abin.test.connectio ... -
Java 数组,List,Itarator循环
2011-06-19 16:01 2307package com.abin.test.connect ... -
JAVA DBClass操作数据库,这样算不算单列模式
2011-06-19 14:53 1255到底怎样才算单列模式,单列模式事什么概念 package c ... -
Oracle日期函数集锦
2011-06-16 20:55 933Oracle日期函数集锦(一) 一、 常用日期数据格式 1 ... -
java 页面传送数组
2011-06-15 14:56 25971.可以通过嵌入java代码调用session或者reques ... -
java Calendar当前时间
2011-06-14 13:40 1665Calendar c = Calendar.getIn ...
相关推荐
### 基于Socket的Java网络编程集粹 #### 核心知识点概述: 本文将深入探讨基于Socket的Java网络编程技术及其应用场景。Socket是网络通信的基础之一,它为应用程序提供了在不同计算机之间发送数据的能力。Java作为...
VB.NET是一种基于.NET Framework的编程语言,由微软公司开发,旨在提供一种更加直观和简洁的编程方式,尤其适合Windows应用程序的开发。这本书“VB.NET编程技巧与实例集粹”是针对初学者和有一定基础的开发者设计的...
在C语言编程中,命令行参数是一种常见的交互方式,它允许用户在运行程序时通过命令行传递参数给程序,从而控制程序的行为。合理地利用命令行参数可以显著提升程序的灵活性和效率。 #### 二、命令行参数的基本概念 ...
在IT行业中,Java是一种广泛应用的面向对象的编程语言,尤其在企业级应用开发领域占据了重要地位。"JAVA经验集粹_新手乐园(含N多.txt格式文档).rar" 这个压缩包文件显然是为Java初学者量身打造的一份宝贵资源。它...
VB.NET编程实例与技巧集粹VB.NET编程实例与技巧集粹VB.NET编程实例与技巧集粹VB.NET编程实例与技巧集粹VB.NET编程实例与技巧集粹VB.NET编程实例与技巧集粹VB.NET编程实例与技巧集粹VB.NET编程实例与技巧集粹VB.NET...
Java常见问题集粹
Visual C# 2008 核心技术与最佳编程实例集粹 part2,共三部分 罗斌,中国水利水电出版社
Visual C# 2008 核心技术与最佳编程实例集粹,part1,共三部分。 罗斌,中国水利水电出版社
《Visual Basic 实用程序集粹》是一本专为VB(Visual Basic)开发者设计的资源宝典,涵盖了多种实用的编程工具和技巧。这本书共计482页,旨在帮助程序员提高开发效率,解决实际工作中遇到的问题。书中包含的源码库...
VB_NET.编程技巧与实例集粹
《VB.NET编程技巧与实例集粹》是一本深入浅出的教程,专为那些希望提升VB.NET编程技能的开发者设计。这本书以丰富的实例为引导,旨在帮助读者掌握VB.NET的核心概念、语法特性以及实用技巧。VB.NET是.NET框架下的一种...
《Visual C# 2008编程实例集粹》光盘 (2/3)
《Visual C# 2008编程实例集粹》光盘内容及其使用 _______________________________________________________________________________ 一、使用方法: 本光盘提供了本书所有实例程序的源代码文件和相关数据库文件。...
VB.NET编程技巧与实例集粹.pdf
VB.NET编程实例与技巧集粹(随书源码).part1.rar 压缩后30多M,分2个包上传! 教材.pdf 39M, csdn.net 网上有下载,就不上传了。
Visual C# 2008 核心技术与最佳编程实例集粹,part3,共三部分。 罗斌,中国水利水电出版社
《Visual C# 2008编程实例集粹》光盘.part3.rar