- 浏览: 112228 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
Stero:
多谢介绍!
JAVA性能/负载/压力测试工具 -
kingterrors:
JS一些正规表达式,方便大家学习 -
highill:
引用如果不需要交互的就用TagSupport,否则如果不需要交 ...
TagSupport与BodyTagSupport的区别 -
whq329:
汗,报错啦,
楼主这也敢写blog上来!
javascript:后退并刷新页面 -
rancococ:
你们这老板也太水了嘛。。。
我被公司老总忽悠了,
1. Client/Server Networking
Java通过socket来完成它所有的网络底层的通讯,socket是一种通讯的通道,通过它可以将数据通过特定的端中发送及接收。Java中的socket可以分成二大类:
(1) Datagram Sockets:数据包socket;
(2) Stream Sockets:流socket;
1.2 Datagram Socket
Datagram socket使用UDP来实现数据通讯,因此它不能保证数据能够到达目的地,但是由于它不需要专用的网络链接,所以它所需的资源相对少的多。
Datagram以包的方式发送数据,但它不能保证这些数据包以特定的顺序到达目的,因此包中往往需要包含序列号的信息,接收方可以根据序列号的信息决定是否所有的包都已收到,并按正常顺序重组这些包。
Java通过两个类DatagramSocket和DatagramPacket来支持Datagram socket。DatagramSocket实现了Datagram socket的基本功能,而DatagramPacket则提供了对包的一些支持。
DatagramSocket的几个重要方法:
(1) DatagramSocket():随机绑定一个有效的端口;
(2) DatagramSocket(int port):绑定指定的端口;
(3) Void send(DatagramPacket p):发送数据报,由于目的地的地址信息已包含在数据报中,所以不需要在本函数中提供地址信息;
(4) synchronized void receive(DatagramPacket p):接收数据包,线程安全;
(5) synchronized void close():关闭socket;
在DatagramSocket中并不区分ServerSocket和ClientSocket,如果一定要区分,那么发送的是client,而接收的是server。
DatagramPacket有以几个重要的方法:
(1) DatagramPacket(byte ibuf[], int ilength):用于接收数据报;
(2) DatagramPacket(byte ibuf[], int ilength, InetAddressiaddr, int iport):用于发送的数据报;
(3) byte[] getData()
(4) int getLength()
以下是完整的Datagram Socket的例子:
接收端,Server端代码:
import java.io.*;
import java.net.*;
class FortuneServer1 extends Thread
{
DatagramSocket ServerSocket;
public FortuneServer1()
{
super("FortuneServer1");
try
{
ServerSocket = new DatagramSocket(1114);
System.out.println("FortuneServer up and running...");
}
catch (SocketException e)
{
System.err.println("Exception: couldn't create datagram socket");
System.exit(1);
} }
public static void main(String[] args)
{
FortuneServer1 server = new FortuneServer1();
server.start();
}
public void run()
{
if (ServerSocket == null)
return;
while (true)
{
try
{
InetAddress address;
int port;
DatagramPacket packet;
byte[] data = new byte[256];
int num = 1;
packet = new DatagramPacket(data, data.length);
ServerSocket.receive(packet);
address = packet.getAddress();
port = packet.getPort();
File inFile = new File("Fortunes.txt");
FileInputStream inStream = new FileInputStream(inFile);
if (inStream.read(data) <= 0)
{
System.err.println("Error: couldn't read fortunes");
}
packet = new DatagramPacket(data, data.length, address, port);
ServerSocket.send(packet);
}
catch (Exception e)
{
System.err.println("Exception: " + e);
e.printStackTrace();
} } } }
说明:
(1) 这个例子中接收端的socket使用了多线程,多线程的概念可以参考本文的多线程部分;
(2) 在构造函数中创建了DatagramSocket,并且使用了1114这个端口;
(3) 本例子的关键函数是run,它使用了死循环,在循环中使用了receive这方法来临听1114端口,如果1114端口没有请求数据到来,那么这个程序就一直停留在receive这个位置,不再往下执行;
(4) 当1114端有数据时,receive方法将接收到的DatagramPacket数据包放在packet这个对象中,然后解析其中的数据,获取发送方的地址信息;
(5) 然后再创建DatagramPacket包,并填充数据,发送到原接收端。
以下是发送端的代码:
import java.io.*;
import java.net.*;
class FortuneClient
{
public static void main(String args[])
{
FortuneClient client = new FortuneClient();
System.out.println(client.getMessage());
}
public String getMessage()
{
String fortune;
try {
DatagramSocket socket;
DatagramPacket packet;
byte[] data = new byte[256];
socket = new DatagramSocket();
packet = new DatagramPacket(data, data.length,InetAddress.getByName("127.0.0.1"), 1114);
socket.send(packet);
packet = new DatagramPacket(data, data.length);
socket.receive(packet);
fortune = new String(packet.getData(), 0);
socket.close();
}
catch (UnknownHostException e) {
System.err.println("Exception: host could not be found");
return null;
}
catch (Exception e) {
System.err.println("Exception: " + e);
e.printStackTrace();
return null;
}
return fortune;
} }
客户端的代码与服务器端的代码基本相同,只是没有了循环,并且处理步骤与服务器端的基本相反。这也说明了Datagram Socket不真正区分Server和Client。
1.3 Stream Socket
Stream Socket与Datagram Socket不同,它有一个永久性的链接,可以确保数据可靠的发送到对方。但是Stream Socket所占的资源更多。
Java主要通过Socket及ServerSocket来实现Stream Socket,一个用于客户端,另一个用户服务器端。
Socket类的几个重要方法如下:
(1) Socket(String host, int port)
(2) Socket(InetAddress address, int port)
(3) synchronized void close()
(4) InputStream getInputStream()
(5) OutputStream getOutputStream()
可以看出Stream Socket中的Socket与Datagram Socket中的Socket的区别:
(1) 在构造函数中,这里需要指定服务器的地址与端口,用于它发送数据之前建立链接,而Datagram的Socket不需要建立链接,它仅需要在要发送的数据包中包含地址信息即可;
(2) Stream Socket的两个重要方法和其它流的方法类似,而且在操作上也相似,其实在操作Stream Socket时,只要建立了链接,那么以后的操作和流的操作一样了,你可以忘了你在操作Socket,只当做自己在操作普通的流。
ServerSocket有以下几个重要的方法:
(1) ServerSocket(int port):监听指定端口,监听时间为默认值50;
(2) ServerSocket(int port, int count):监听指定端口,并指定监听时间;
(3) ServerSocket(int port, int backlog, InetAddress bindAddr):只接收指定接口发过来的数据;
(4) Socket accept():accpet方法会返回一个Socket对象,使用该Socket对象的getInputStream及getOutputStream方法获取输入及输出流。由此可见无论是服务器端还是客户端,它们都是通过Socket对象来收发数据的。程序执行到accpet时会进入监听状态,不再向下执行一直到接收到数据。
(5) void close()
以下是关于Stream Socket的一个例子,在这个例子中使用单独的二个类Receiver和Sender负责对指定的输入及输出流进行操作,用另一个类SocketPerformer来创建Receiver和Sender这两个类的实例,并传入指定的输入及输出流,而在Client及Server这两个类中,负责创建SocketPerformer对象,并传入指定的Socket。因此这五个类在功能上分为三层,第一层负责对流进行操作,第二层负责创建指定的Socket流,并这些Socket流传到第一层,第三层负责创建Socket并将这些Socket传到第二层。
Receriver代码:
package socketChat;
import java.io.BufferedReader;
public class Receiver extends Thread {
BufferedReader reader;
public Receiver(BufferedReader theSocketReader) {
reader = theSocketReader;
}
public void run() {
while (true) {
try {
String words = reader.readLine(); System.out.println("\r\n<<< " + words);
} catch (Exception e) {
e.printStackTrace();
return;
} } }}
Sender代码:
package socketChat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class Sender extends Thread {
PrintWriter writer;
public Sender(PrintWriter theWriter) {
writer = theWriter;
}
public void run() {
try {
while (true) {
BufferedReader consoleReader = new BufferedReader(
new InputStreamReader(System.in));
String userInput = consoleReader.readLine();
writer.write(userInput + "\r\n");
writer.flush(); // send the data in buffer immediately
}
} catch (Exception e) {
e.printStackTrace();
return;
} }}
SocketPerformer代码:
package socketChat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class SocketPerformer {
Socket socket;
public SocketPerformer(Socket theSoc){
socket = theSoc;
}
public void execut() throws Exception{
BufferedReader socketReader = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
PrintWriter socketWriter = new PrintWriter(socket.getOutputStream());
System.out.println("connection built !");
Receiver rec = new Receiver(socketReader);
rec.start();
Sender sender = new Sender(socketWriter);
sender.start();
}}
Server代码:
package socketChat;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(30000, 5);
Socket socket = null;
System.out.println("waiting incoming connection...");
socket = server.accept();
System.out.println("a connection built!");
System.out.println("the peer ip is: " + socket.getInetAddress().getHostAddress());
new SocketPerformer(socket).execut();
server.close();
}}
Client端代码如下:
package socketChat;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws Exception {
String ip = "127.0.0.1";
int port = 30000;
System.out.println("connecting to server: " + ip
+ " at port: " + port + " ...");
Socket soc = new Socket(ip, port);
new SocketPerformer(soc).execut();
}}
2. 其它
(1) 常量定义以final做修饰符,如final int I = 3;final还可以用在class及method上,如果用在class上,那么该class不能被继承,如果用在method上,那么该method不能被重载
(2) 类变量定义:static int sum
(3) 判断对象类型:objName instanceof className,如"helloWorld" instanceof String,判断的结果是true
(4) 提取对象的类名:objName.getClass().getName()
(5) java.lang:Java最基本的包,包含java语言最基本的定义
(6) java.util:包含如Date,及基本的集合类,如Vector、Hashtable等
(7) java.io:包含输入输出的定义
(8) java.net:包含如Socket等
(9) java.awt:用于Window界面开发
(10) java.applet:用于applet开发
(11) null关键字引用null对象,注意大小写
(12) 每个基本的数据类型如int,都有相应的类与之对应中Int
(13) 构造函数名与类名相同,并且不需要返回类型,即在构造函数前不需要加类型修饰符
(14) 调用自身的构造函数:this(参数列表);
(15) 调用父类的构造函数:super(参数列表);
(16) 调用父类已被重载的函数:super.方法名(参数列表);
(17) 在同一文件中可以有多个类的定义,但只能有一个类是public并且类名与文件一样,该文件编译成功后会生成多个.class文件,与类的定义一一对应;
(18) 接口比抽象类功能强有:抽象类属于特定的类结构树中,它不能被其它树中的类共享;
(19) 接口的定义与类的定义类似,只需将class改成interface即可,但接口定义必须是public或者缺省的(package);
(20) 在接口中可以定义方法和变量,接口中的定义的方法应是public并且是abstract的(缺省);变量的定义必须是public static final(缺省);
(21) String.copyValueOf(buffer, 0, offset):用于从字符数组中取出字符,并形成字符串;
(22) new String(buf, 0, count)
(23) System.in(标准输入)是一个InputStream;
(24) System.err是一个PrintStream;
(25) System.out是一个PrintStream;
网络编程
在tcp/ip协议中,ip地址用4个字节,也就是32位的二进制来表示,称为ipv4。
Ip地址只能保证把数据送到该计算机,但不能保证把这些数据交给那个网络程序,因此,每个发送的网络数据包的头部都含有一个被称为“端口”的部分,它是一个整数,用于表示该数据帧交给那个应该程序来处理。还必须为网络应用程序指定一个端口号,计算机上不能有2个使用同一端口的程序运行。
当数据到达第一个网络程序所在的计算机后,驱动程序根据数据包中的端口号,就知道将这个数据包交给这个网络程序。
Udp与tcp
Tcp是面向连接的通信协议,提供2台计算机之间的可靠无差错的数据传输。应用程序利用tcp进行通信时,源和目的直接会建立一个虚拟链接。
Udp是无连接通信协议,udp不保证可靠数据的传输,但能够向若干个目标发送数据,接收发自若干个源的数据。
数据包的基本格式:
协议类型
源ip
目的ip
源端口
目的端口
帧序号
帧数据
其中协议类型用于区分tcp和udp。
Socket
Socket是网络驱动层提供给应用程序的接口和一种机制。
可以认为socket是应用程序创建的一个港口码头,应用程序只要把装着货物的集装箱(要发送的数据)放在码头上,就算完成了货物的运送,剩下的工作就由货运公司(驱动程序)去处理了。
对接收方来说,应用程序也要创建一个码头,然后就一直等待该码头的货物到达,最后从码头上取走货物(数据)。
Socket在应用程序中创建,通过一个绑定机制与驱动程序建立关系,告诉自己所对应的ip和port。此后,应用程序送给socket的数据,由socket交给驱动程序向网络上发送。计算机从网络收到与该socket绑定的ip+port相关数据后,由驱动程序交给socket,应用程序便可以从该sokcet中取得接收到的数据。
Java分别为udp和tcp2种通信协议提供了相应的编程类,存放在java.net包中,与udp对应的是DatagramSocket,与tcp对应的是ServerSocket(用于服务器)和Socket(用于客户端)。
Java编写udp网络程序
Java.net.DategramSocket类 的构造函数主要有以下几种:
Public DatagramSocket() throws SocketException
Public DatagramSocket(int port) throws SocketException
Public DatagramSocket(int port,InetAddress laddr) throws SocketException
编写发送程序时,我们可以用第一个构造函数(创建DatagramSocket对象时,不指定端口号,系统就会为我们分配一个端口号)。
注意:第三个构造函数创建DatagramSocket对象,除了指定自己想要的端口号外,还可以指定相关的ip地址,这个情况适合计算机上有多个网卡和多个ip的情况。其实对于只有一块网卡的情况,如果在这里指定了ip地址,反而会给程序带来很大的不方便,因为这个网络程序只能在具有这个ip的计算机上运行,而不能在其他计算机上面运行。
编写接收程序时,我们必须自己指定一个端口号,而不让系统随即分配,可以使用第二个构造函数。
如果程序不在使用某个sokcet,应该调用DatagramSocket.close()方法,关闭这个socket,通知驱动程序释放为这个socket所保留的资源,系统就可以将这个socket所占用的端口号重新分配给其他程序使用。
在发送数据时,我们用Datagram.send()方法,
public void send(DatagramPacket p) throws IOException
在接收数据时,我们用Datagram.receice()方法,
public void receive(DatagramPacket p) throws IOException
这2个方法都需要传递一个DatagramPacket类的实例对象,如果把DatagramSocket比作创建的码头,那么DatagramPacket就是我们发送和接收数据的集装箱。
DatagramPacket类构造函数主要有:
public DatagramPacket(byte[] buf,int length)
public DatagramPacket(byte[] buf, int length, InetAddress address, int port)
在接收数据时,我们应该用第一个构造函数来创建接收数据的DatagramPacket对象。
在发送数据时,我们必须指定接收方socket的地址和端口号,所以我们应该用第二个构造函数来创建发送数据的DatagramPacket对象。
最简单的udp程序:接收应用程序的端口号为3000。发送程序的端口号由系统分配。
import java.io.IOException;
import java.net.*;
public class UdpSend
{
public static void main(String [] args)
{
DatagramSocket ds = null;
try { ds = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
}
String str="hello world";
DatagramPacket dp = null;
try {dp = new DatagramPacket(str.getBytes(),str.length(),InetAddress.getByName("192.168.1.101"),3000);
} catch (UnknownHostException e1) {
e1.printStackTrace();
}
try {ds.send(dp);
} catch (IOException e2) {
e2.printStackTrace();
}
ds.close();
}
}
import java.io.IOException;
import java.net.*;
public class UdpRecv
{
public static void main(String [] args )
{
DatagramSocket ds=null;
try{ds=new DatagramSocket(3000);}
catch(SocketException e){e.printStackTrace();}
byte[] buf=new byte[1024];
DatagramPacket dp=null;
dp=new DatagramPacket(buf,1024);
try { ds.receive(dp);
} catch (IOException e1) { // TODO Auto-generated catch block
e1.printStackTrace();
}
String str=new String(dp.getData(),0,dp.getLength()) + " from " + dp.getAddress().getHostAddress() + ":" +dp.getPort();
//public String(byte[] byte)是将数组中的所有元素都转换成字符串,包括哪些没有填充的单元
// public String(byte[] bytes,int offset,int length)是将字节数组中从offset开始,往后一共length
//个单元的内容转换成字符串
System.out.println(str);
ds.close();
}
}
Java编写tcp网络程序:
利用tcp协议进行通信的2个应用程序,是有主次之分的。一个称为服务器程序,另外一个称为客户机程序。2者的能够和编写方法大不一样。
服务器和客户端交互过程:
1、服务器程序创建一个ServerSocket,然后调用accept方法等待客户来链接。
2、客户端程序创建一个Socket并请求与服务器建立连接。
3、服务器接收客户的连接请求,并创建一个新的sokcet与该客户建立专线连接。
4、刚才建立了连接的2个socket在一个单独的线程(由服务器程序创建)上对话。
5、服务器开始等待新的连接请求。
ServerScoket
构造方法:
public ServerSocket() throws IOException
public ServerSocket(int port) throws IOException
public ServerSocket(int port,int backlog) throws IOException
public ServerSocket(int port,int backlog,InetAddress bindAddr) throws IOException
第一个:没有与任何端口号绑定,不能直接使用,还要调用bind方法才能完成构造函数所完成的工作。
第二个:创建serverSocket对象,可以将这个serverSocket绑定到一个指定的端口上,作为服务器程序,端口号必须事先指定,其他客户才能根据这个号码进行连接。所以将端口号指定为0的情况并不常见。
第三个:创建serverSocket对象,就是在第二个构造函数的基础上,我们根据backlog参数指定,在服务器忙时,可以与之保持连接请求的等待客户数量,对于第二个构造函数,没有指定这个参数,则使用默认的数量,大小为50。
第四个:创建serverSocket对象,除了指定第三个构造函数中的参数外,还可以指定相关的ip地址,这种情况适用于计算机上有多个网卡和多个ip的情况。对于一般情况只有一块网卡的情况,就不用指定ip了。
第二个构造方法比较适合创建我们的serversocket对象。
Socket
客户端于服务器建立连接,首先必须创建一个sokcet对象,它的构造方法:
public Socket()
public Socket(String host,int port)throws UnknownHostException,IOException
public Socket(InetAddress address,int port) throws IOException
public Socket(String host,int port,InetAddress localAddr,int localPort) throws IOException
public Socket(InetAddress address,int port,InetAddress localAddr, int localPort) throws IOException
第一个:能够创建sokcet对象,不与任何服务器建立连接,不能直接使用,还要调用connect方法才能完成构造函数所完成的工作。
第二个:创建socket对象后,会根据参数去连接在特定地址和端口上运行的服务器程序,接收字符串格式的地址。
第三个:创建socket对象后,会根据参数去连接在特定地址和端口上运行的服务器程序,接收InetAddress对象所包装的地址。
第四个和第五个:在第二个和第三个构造函数的基础上,还指定了本地sokcet所绑定的ip地址和端口号,由于客户端的端口号的选择不重要,所以一般情况下,我们不会使用这2个构造函数。
我们选择第二个构造函数来创建客户端的socket对象并与服务器建立连接。
服务器端程序调用serversokcet.accept方法等待客户的连接请求,一旦accept接收了客户连接请求,该方法将返回一个与该客户建立专线连接的sokcet对象,不用程序去创建这个socket对象。当客户端和服务器端的2个sokcet建立了专线连接后,连接的一端能向另外一端连续写入字节,也能从另外一端连续读入字节,就是建立了专线连接的2个sokcet是以io流的方式进行数据交换的。Java提供了sokcet.getInputStream方法返回socket的输入流对象,socket..getOutputstrram方法返回sokcet的输出流对象。只要连接的一端向该输出流对象写入了数据,连接的另一端就能从输入流对象这读取到这些数据。
简单的服务器程序:
import java.net.*;
import java.io.*;
public class TcpServer {
public static void main(String[] args) {
try{
ServerSocket ss=new ServerSocket(8001);
Socket s=ss.accept();
InputStream ips=s.getInputStream();
OutputStream ops=s.getOutputStream();
ops.write("welcome to www!".getBytes());//通过输出流首先向客户端发送一串字符
byte [] buf=new byte[1024];
int len=ips.read(buf);//通过输入流读取客户端发来的信息,并保存到一个字节数组中
System.out.println(new String(buf,0,len));
ips.close();
ops.close();
s.close();
ss.close();
}
catch(Exception e) {e.printStackTrace();}
}
}
上面的代码如果在telnet中输入一个字母,就会发送到服务器端,马上就退出了。为了实现客户端输入一行字母,代码修改如下:
import java.net.*;
import java.io.*;
public class TcpServer {
public static void main(String[] args) {
try{
ServerSocket ss=new ServerSocket(8001);
Socket s=ss.accept();
InputStream ips=s.getInputStream();
OutputStream ops=s.getOutputStream();
ops.write("welcome to www!".getBytes());//通过输出流首先向客户端发送一串字符
BufferedReader br=new BufferedReader(new InputStreamReader(ips));;
//byte [] buf=new byte[1024];
//int len=ips.read(buf);//通过输入流读取客户端发来的信息,并保存到一个字节数组中
//System.out.println(new String(buf,0,len));
System.out.println(br.readLine());
//ips.close();
br.close();//关闭包装类,会自动关闭包装类中所包装的底层类。所以不用调用ips.close()
ops.close();
s.close();
ss.close();
}
catch(Exception e)
{e.printStackTrace();}
}
}
完善的tcp服务器程序模型:
import java.io.*;
import java.net.*;
public class Servicer implements Runnable{
Socket s;
public Servicer(Socket s)
{
this.s=s;
}
public void run()
{
try{
InputStream ips=s.getInputStream();
OutputStream ops=s.getOutputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(ips));
DataOutputStream dos=new DataOutputStream(ops);
while(true)
{
String str=br.readLine();
if(str.equalsIgnoreCase("quit"))
break;
String strEcho=(new StringBuffer(str)).toString();
//String strEcho=(new StringBuffer(str).reverse()).toString();
dos.writeBytes(str + "--->" + strEcho + System.getProperty("line.separator"));
}
br.close();
dos.close();
s.close();
}
catch(Exception e){e.printStackTrace();}
}
}
class TcpServer
{
public static void main(String [] args)
{
try{
ServerSocket ss=new ServerSocket(8001);
while(true)
{
Socket s=ss.accept();
new Thread(new Servicer(s)).start();
}
}
catch(Exception e1){e1.printStackTrace();}
}
}
import java.net.*;
import java.io.*;
public class TcpClient {
public static void main(String[] args) {
try{
if(args.length<2)
{
System.out.println("Usage:java Tcpclient serverIP serverPort");
return;
}
Socket s=new Socket(InetAddress.getByName(args[0]),Integer.parseInt(args[1]));
InputStream ips=s.getInputStream();
OutputStream ops=s.getOutputStream();
BufferedReader brkey=new BufferedReader(new InputStreamReader(System.in));
DataOutputStream dos=new DataOutputStream(ops);
BufferedReader brnet=new BufferedReader(new InputStreamReader(ips));
while(true)
{
String strW=brkey.readLine();
dos.writeBytes(strW + System.getProperty("line.separator"));
if (strW.equalsIgnoreCase("quit"))
break;
else
System.out.println(brnet.readLine());
}
dos.close();
brnet.close();
brkey.close();
s.close();
}
catch(Exception e){e.printStackTrace();
}
}
}
Java通过socket来完成它所有的网络底层的通讯,socket是一种通讯的通道,通过它可以将数据通过特定的端中发送及接收。Java中的socket可以分成二大类:
(1) Datagram Sockets:数据包socket;
(2) Stream Sockets:流socket;
1.2 Datagram Socket
Datagram socket使用UDP来实现数据通讯,因此它不能保证数据能够到达目的地,但是由于它不需要专用的网络链接,所以它所需的资源相对少的多。
Datagram以包的方式发送数据,但它不能保证这些数据包以特定的顺序到达目的,因此包中往往需要包含序列号的信息,接收方可以根据序列号的信息决定是否所有的包都已收到,并按正常顺序重组这些包。
Java通过两个类DatagramSocket和DatagramPacket来支持Datagram socket。DatagramSocket实现了Datagram socket的基本功能,而DatagramPacket则提供了对包的一些支持。
DatagramSocket的几个重要方法:
(1) DatagramSocket():随机绑定一个有效的端口;
(2) DatagramSocket(int port):绑定指定的端口;
(3) Void send(DatagramPacket p):发送数据报,由于目的地的地址信息已包含在数据报中,所以不需要在本函数中提供地址信息;
(4) synchronized void receive(DatagramPacket p):接收数据包,线程安全;
(5) synchronized void close():关闭socket;
在DatagramSocket中并不区分ServerSocket和ClientSocket,如果一定要区分,那么发送的是client,而接收的是server。
DatagramPacket有以几个重要的方法:
(1) DatagramPacket(byte ibuf[], int ilength):用于接收数据报;
(2) DatagramPacket(byte ibuf[], int ilength, InetAddressiaddr, int iport):用于发送的数据报;
(3) byte[] getData()
(4) int getLength()
以下是完整的Datagram Socket的例子:
接收端,Server端代码:
import java.io.*;
import java.net.*;
class FortuneServer1 extends Thread
{
DatagramSocket ServerSocket;
public FortuneServer1()
{
super("FortuneServer1");
try
{
ServerSocket = new DatagramSocket(1114);
System.out.println("FortuneServer up and running...");
}
catch (SocketException e)
{
System.err.println("Exception: couldn't create datagram socket");
System.exit(1);
} }
public static void main(String[] args)
{
FortuneServer1 server = new FortuneServer1();
server.start();
}
public void run()
{
if (ServerSocket == null)
return;
while (true)
{
try
{
InetAddress address;
int port;
DatagramPacket packet;
byte[] data = new byte[256];
int num = 1;
packet = new DatagramPacket(data, data.length);
ServerSocket.receive(packet);
address = packet.getAddress();
port = packet.getPort();
File inFile = new File("Fortunes.txt");
FileInputStream inStream = new FileInputStream(inFile);
if (inStream.read(data) <= 0)
{
System.err.println("Error: couldn't read fortunes");
}
packet = new DatagramPacket(data, data.length, address, port);
ServerSocket.send(packet);
}
catch (Exception e)
{
System.err.println("Exception: " + e);
e.printStackTrace();
} } } }
说明:
(1) 这个例子中接收端的socket使用了多线程,多线程的概念可以参考本文的多线程部分;
(2) 在构造函数中创建了DatagramSocket,并且使用了1114这个端口;
(3) 本例子的关键函数是run,它使用了死循环,在循环中使用了receive这方法来临听1114端口,如果1114端口没有请求数据到来,那么这个程序就一直停留在receive这个位置,不再往下执行;
(4) 当1114端有数据时,receive方法将接收到的DatagramPacket数据包放在packet这个对象中,然后解析其中的数据,获取发送方的地址信息;
(5) 然后再创建DatagramPacket包,并填充数据,发送到原接收端。
以下是发送端的代码:
import java.io.*;
import java.net.*;
class FortuneClient
{
public static void main(String args[])
{
FortuneClient client = new FortuneClient();
System.out.println(client.getMessage());
}
public String getMessage()
{
String fortune;
try {
DatagramSocket socket;
DatagramPacket packet;
byte[] data = new byte[256];
socket = new DatagramSocket();
packet = new DatagramPacket(data, data.length,InetAddress.getByName("127.0.0.1"), 1114);
socket.send(packet);
packet = new DatagramPacket(data, data.length);
socket.receive(packet);
fortune = new String(packet.getData(), 0);
socket.close();
}
catch (UnknownHostException e) {
System.err.println("Exception: host could not be found");
return null;
}
catch (Exception e) {
System.err.println("Exception: " + e);
e.printStackTrace();
return null;
}
return fortune;
} }
客户端的代码与服务器端的代码基本相同,只是没有了循环,并且处理步骤与服务器端的基本相反。这也说明了Datagram Socket不真正区分Server和Client。
1.3 Stream Socket
Stream Socket与Datagram Socket不同,它有一个永久性的链接,可以确保数据可靠的发送到对方。但是Stream Socket所占的资源更多。
Java主要通过Socket及ServerSocket来实现Stream Socket,一个用于客户端,另一个用户服务器端。
Socket类的几个重要方法如下:
(1) Socket(String host, int port)
(2) Socket(InetAddress address, int port)
(3) synchronized void close()
(4) InputStream getInputStream()
(5) OutputStream getOutputStream()
可以看出Stream Socket中的Socket与Datagram Socket中的Socket的区别:
(1) 在构造函数中,这里需要指定服务器的地址与端口,用于它发送数据之前建立链接,而Datagram的Socket不需要建立链接,它仅需要在要发送的数据包中包含地址信息即可;
(2) Stream Socket的两个重要方法和其它流的方法类似,而且在操作上也相似,其实在操作Stream Socket时,只要建立了链接,那么以后的操作和流的操作一样了,你可以忘了你在操作Socket,只当做自己在操作普通的流。
ServerSocket有以下几个重要的方法:
(1) ServerSocket(int port):监听指定端口,监听时间为默认值50;
(2) ServerSocket(int port, int count):监听指定端口,并指定监听时间;
(3) ServerSocket(int port, int backlog, InetAddress bindAddr):只接收指定接口发过来的数据;
(4) Socket accept():accpet方法会返回一个Socket对象,使用该Socket对象的getInputStream及getOutputStream方法获取输入及输出流。由此可见无论是服务器端还是客户端,它们都是通过Socket对象来收发数据的。程序执行到accpet时会进入监听状态,不再向下执行一直到接收到数据。
(5) void close()
以下是关于Stream Socket的一个例子,在这个例子中使用单独的二个类Receiver和Sender负责对指定的输入及输出流进行操作,用另一个类SocketPerformer来创建Receiver和Sender这两个类的实例,并传入指定的输入及输出流,而在Client及Server这两个类中,负责创建SocketPerformer对象,并传入指定的Socket。因此这五个类在功能上分为三层,第一层负责对流进行操作,第二层负责创建指定的Socket流,并这些Socket流传到第一层,第三层负责创建Socket并将这些Socket传到第二层。
Receriver代码:
package socketChat;
import java.io.BufferedReader;
public class Receiver extends Thread {
BufferedReader reader;
public Receiver(BufferedReader theSocketReader) {
reader = theSocketReader;
}
public void run() {
while (true) {
try {
String words = reader.readLine(); System.out.println("\r\n<<< " + words);
} catch (Exception e) {
e.printStackTrace();
return;
} } }}
Sender代码:
package socketChat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class Sender extends Thread {
PrintWriter writer;
public Sender(PrintWriter theWriter) {
writer = theWriter;
}
public void run() {
try {
while (true) {
BufferedReader consoleReader = new BufferedReader(
new InputStreamReader(System.in));
String userInput = consoleReader.readLine();
writer.write(userInput + "\r\n");
writer.flush(); // send the data in buffer immediately
}
} catch (Exception e) {
e.printStackTrace();
return;
} }}
SocketPerformer代码:
package socketChat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class SocketPerformer {
Socket socket;
public SocketPerformer(Socket theSoc){
socket = theSoc;
}
public void execut() throws Exception{
BufferedReader socketReader = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
PrintWriter socketWriter = new PrintWriter(socket.getOutputStream());
System.out.println("connection built !");
Receiver rec = new Receiver(socketReader);
rec.start();
Sender sender = new Sender(socketWriter);
sender.start();
}}
Server代码:
package socketChat;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(30000, 5);
Socket socket = null;
System.out.println("waiting incoming connection...");
socket = server.accept();
System.out.println("a connection built!");
System.out.println("the peer ip is: " + socket.getInetAddress().getHostAddress());
new SocketPerformer(socket).execut();
server.close();
}}
Client端代码如下:
package socketChat;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws Exception {
String ip = "127.0.0.1";
int port = 30000;
System.out.println("connecting to server: " + ip
+ " at port: " + port + " ...");
Socket soc = new Socket(ip, port);
new SocketPerformer(soc).execut();
}}
2. 其它
(1) 常量定义以final做修饰符,如final int I = 3;final还可以用在class及method上,如果用在class上,那么该class不能被继承,如果用在method上,那么该method不能被重载
(2) 类变量定义:static int sum
(3) 判断对象类型:objName instanceof className,如"helloWorld" instanceof String,判断的结果是true
(4) 提取对象的类名:objName.getClass().getName()
(5) java.lang:Java最基本的包,包含java语言最基本的定义
(6) java.util:包含如Date,及基本的集合类,如Vector、Hashtable等
(7) java.io:包含输入输出的定义
(8) java.net:包含如Socket等
(9) java.awt:用于Window界面开发
(10) java.applet:用于applet开发
(11) null关键字引用null对象,注意大小写
(12) 每个基本的数据类型如int,都有相应的类与之对应中Int
(13) 构造函数名与类名相同,并且不需要返回类型,即在构造函数前不需要加类型修饰符
(14) 调用自身的构造函数:this(参数列表);
(15) 调用父类的构造函数:super(参数列表);
(16) 调用父类已被重载的函数:super.方法名(参数列表);
(17) 在同一文件中可以有多个类的定义,但只能有一个类是public并且类名与文件一样,该文件编译成功后会生成多个.class文件,与类的定义一一对应;
(18) 接口比抽象类功能强有:抽象类属于特定的类结构树中,它不能被其它树中的类共享;
(19) 接口的定义与类的定义类似,只需将class改成interface即可,但接口定义必须是public或者缺省的(package);
(20) 在接口中可以定义方法和变量,接口中的定义的方法应是public并且是abstract的(缺省);变量的定义必须是public static final(缺省);
(21) String.copyValueOf(buffer, 0, offset):用于从字符数组中取出字符,并形成字符串;
(22) new String(buf, 0, count)
(23) System.in(标准输入)是一个InputStream;
(24) System.err是一个PrintStream;
(25) System.out是一个PrintStream;
网络编程
在tcp/ip协议中,ip地址用4个字节,也就是32位的二进制来表示,称为ipv4。
Ip地址只能保证把数据送到该计算机,但不能保证把这些数据交给那个网络程序,因此,每个发送的网络数据包的头部都含有一个被称为“端口”的部分,它是一个整数,用于表示该数据帧交给那个应该程序来处理。还必须为网络应用程序指定一个端口号,计算机上不能有2个使用同一端口的程序运行。
当数据到达第一个网络程序所在的计算机后,驱动程序根据数据包中的端口号,就知道将这个数据包交给这个网络程序。
Udp与tcp
Tcp是面向连接的通信协议,提供2台计算机之间的可靠无差错的数据传输。应用程序利用tcp进行通信时,源和目的直接会建立一个虚拟链接。
Udp是无连接通信协议,udp不保证可靠数据的传输,但能够向若干个目标发送数据,接收发自若干个源的数据。
数据包的基本格式:
协议类型
源ip
目的ip
源端口
目的端口
帧序号
帧数据
其中协议类型用于区分tcp和udp。
Socket
Socket是网络驱动层提供给应用程序的接口和一种机制。
可以认为socket是应用程序创建的一个港口码头,应用程序只要把装着货物的集装箱(要发送的数据)放在码头上,就算完成了货物的运送,剩下的工作就由货运公司(驱动程序)去处理了。
对接收方来说,应用程序也要创建一个码头,然后就一直等待该码头的货物到达,最后从码头上取走货物(数据)。
Socket在应用程序中创建,通过一个绑定机制与驱动程序建立关系,告诉自己所对应的ip和port。此后,应用程序送给socket的数据,由socket交给驱动程序向网络上发送。计算机从网络收到与该socket绑定的ip+port相关数据后,由驱动程序交给socket,应用程序便可以从该sokcet中取得接收到的数据。
Java分别为udp和tcp2种通信协议提供了相应的编程类,存放在java.net包中,与udp对应的是DatagramSocket,与tcp对应的是ServerSocket(用于服务器)和Socket(用于客户端)。
Java编写udp网络程序
Java.net.DategramSocket类 的构造函数主要有以下几种:
Public DatagramSocket() throws SocketException
Public DatagramSocket(int port) throws SocketException
Public DatagramSocket(int port,InetAddress laddr) throws SocketException
编写发送程序时,我们可以用第一个构造函数(创建DatagramSocket对象时,不指定端口号,系统就会为我们分配一个端口号)。
注意:第三个构造函数创建DatagramSocket对象,除了指定自己想要的端口号外,还可以指定相关的ip地址,这个情况适合计算机上有多个网卡和多个ip的情况。其实对于只有一块网卡的情况,如果在这里指定了ip地址,反而会给程序带来很大的不方便,因为这个网络程序只能在具有这个ip的计算机上运行,而不能在其他计算机上面运行。
编写接收程序时,我们必须自己指定一个端口号,而不让系统随即分配,可以使用第二个构造函数。
如果程序不在使用某个sokcet,应该调用DatagramSocket.close()方法,关闭这个socket,通知驱动程序释放为这个socket所保留的资源,系统就可以将这个socket所占用的端口号重新分配给其他程序使用。
在发送数据时,我们用Datagram.send()方法,
public void send(DatagramPacket p) throws IOException
在接收数据时,我们用Datagram.receice()方法,
public void receive(DatagramPacket p) throws IOException
这2个方法都需要传递一个DatagramPacket类的实例对象,如果把DatagramSocket比作创建的码头,那么DatagramPacket就是我们发送和接收数据的集装箱。
DatagramPacket类构造函数主要有:
public DatagramPacket(byte[] buf,int length)
public DatagramPacket(byte[] buf, int length, InetAddress address, int port)
在接收数据时,我们应该用第一个构造函数来创建接收数据的DatagramPacket对象。
在发送数据时,我们必须指定接收方socket的地址和端口号,所以我们应该用第二个构造函数来创建发送数据的DatagramPacket对象。
最简单的udp程序:接收应用程序的端口号为3000。发送程序的端口号由系统分配。
import java.io.IOException;
import java.net.*;
public class UdpSend
{
public static void main(String [] args)
{
DatagramSocket ds = null;
try { ds = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
}
String str="hello world";
DatagramPacket dp = null;
try {dp = new DatagramPacket(str.getBytes(),str.length(),InetAddress.getByName("192.168.1.101"),3000);
} catch (UnknownHostException e1) {
e1.printStackTrace();
}
try {ds.send(dp);
} catch (IOException e2) {
e2.printStackTrace();
}
ds.close();
}
}
import java.io.IOException;
import java.net.*;
public class UdpRecv
{
public static void main(String [] args )
{
DatagramSocket ds=null;
try{ds=new DatagramSocket(3000);}
catch(SocketException e){e.printStackTrace();}
byte[] buf=new byte[1024];
DatagramPacket dp=null;
dp=new DatagramPacket(buf,1024);
try { ds.receive(dp);
} catch (IOException e1) { // TODO Auto-generated catch block
e1.printStackTrace();
}
String str=new String(dp.getData(),0,dp.getLength()) + " from " + dp.getAddress().getHostAddress() + ":" +dp.getPort();
//public String(byte[] byte)是将数组中的所有元素都转换成字符串,包括哪些没有填充的单元
// public String(byte[] bytes,int offset,int length)是将字节数组中从offset开始,往后一共length
//个单元的内容转换成字符串
System.out.println(str);
ds.close();
}
}
Java编写tcp网络程序:
利用tcp协议进行通信的2个应用程序,是有主次之分的。一个称为服务器程序,另外一个称为客户机程序。2者的能够和编写方法大不一样。
服务器和客户端交互过程:
1、服务器程序创建一个ServerSocket,然后调用accept方法等待客户来链接。
2、客户端程序创建一个Socket并请求与服务器建立连接。
3、服务器接收客户的连接请求,并创建一个新的sokcet与该客户建立专线连接。
4、刚才建立了连接的2个socket在一个单独的线程(由服务器程序创建)上对话。
5、服务器开始等待新的连接请求。
ServerScoket
构造方法:
public ServerSocket() throws IOException
public ServerSocket(int port) throws IOException
public ServerSocket(int port,int backlog) throws IOException
public ServerSocket(int port,int backlog,InetAddress bindAddr) throws IOException
第一个:没有与任何端口号绑定,不能直接使用,还要调用bind方法才能完成构造函数所完成的工作。
第二个:创建serverSocket对象,可以将这个serverSocket绑定到一个指定的端口上,作为服务器程序,端口号必须事先指定,其他客户才能根据这个号码进行连接。所以将端口号指定为0的情况并不常见。
第三个:创建serverSocket对象,就是在第二个构造函数的基础上,我们根据backlog参数指定,在服务器忙时,可以与之保持连接请求的等待客户数量,对于第二个构造函数,没有指定这个参数,则使用默认的数量,大小为50。
第四个:创建serverSocket对象,除了指定第三个构造函数中的参数外,还可以指定相关的ip地址,这种情况适用于计算机上有多个网卡和多个ip的情况。对于一般情况只有一块网卡的情况,就不用指定ip了。
第二个构造方法比较适合创建我们的serversocket对象。
Socket
客户端于服务器建立连接,首先必须创建一个sokcet对象,它的构造方法:
public Socket()
public Socket(String host,int port)throws UnknownHostException,IOException
public Socket(InetAddress address,int port) throws IOException
public Socket(String host,int port,InetAddress localAddr,int localPort) throws IOException
public Socket(InetAddress address,int port,InetAddress localAddr, int localPort) throws IOException
第一个:能够创建sokcet对象,不与任何服务器建立连接,不能直接使用,还要调用connect方法才能完成构造函数所完成的工作。
第二个:创建socket对象后,会根据参数去连接在特定地址和端口上运行的服务器程序,接收字符串格式的地址。
第三个:创建socket对象后,会根据参数去连接在特定地址和端口上运行的服务器程序,接收InetAddress对象所包装的地址。
第四个和第五个:在第二个和第三个构造函数的基础上,还指定了本地sokcet所绑定的ip地址和端口号,由于客户端的端口号的选择不重要,所以一般情况下,我们不会使用这2个构造函数。
我们选择第二个构造函数来创建客户端的socket对象并与服务器建立连接。
服务器端程序调用serversokcet.accept方法等待客户的连接请求,一旦accept接收了客户连接请求,该方法将返回一个与该客户建立专线连接的sokcet对象,不用程序去创建这个socket对象。当客户端和服务器端的2个sokcet建立了专线连接后,连接的一端能向另外一端连续写入字节,也能从另外一端连续读入字节,就是建立了专线连接的2个sokcet是以io流的方式进行数据交换的。Java提供了sokcet.getInputStream方法返回socket的输入流对象,socket..getOutputstrram方法返回sokcet的输出流对象。只要连接的一端向该输出流对象写入了数据,连接的另一端就能从输入流对象这读取到这些数据。
简单的服务器程序:
import java.net.*;
import java.io.*;
public class TcpServer {
public static void main(String[] args) {
try{
ServerSocket ss=new ServerSocket(8001);
Socket s=ss.accept();
InputStream ips=s.getInputStream();
OutputStream ops=s.getOutputStream();
ops.write("welcome to www!".getBytes());//通过输出流首先向客户端发送一串字符
byte [] buf=new byte[1024];
int len=ips.read(buf);//通过输入流读取客户端发来的信息,并保存到一个字节数组中
System.out.println(new String(buf,0,len));
ips.close();
ops.close();
s.close();
ss.close();
}
catch(Exception e) {e.printStackTrace();}
}
}
上面的代码如果在telnet中输入一个字母,就会发送到服务器端,马上就退出了。为了实现客户端输入一行字母,代码修改如下:
import java.net.*;
import java.io.*;
public class TcpServer {
public static void main(String[] args) {
try{
ServerSocket ss=new ServerSocket(8001);
Socket s=ss.accept();
InputStream ips=s.getInputStream();
OutputStream ops=s.getOutputStream();
ops.write("welcome to www!".getBytes());//通过输出流首先向客户端发送一串字符
BufferedReader br=new BufferedReader(new InputStreamReader(ips));;
//byte [] buf=new byte[1024];
//int len=ips.read(buf);//通过输入流读取客户端发来的信息,并保存到一个字节数组中
//System.out.println(new String(buf,0,len));
System.out.println(br.readLine());
//ips.close();
br.close();//关闭包装类,会自动关闭包装类中所包装的底层类。所以不用调用ips.close()
ops.close();
s.close();
ss.close();
}
catch(Exception e)
{e.printStackTrace();}
}
}
完善的tcp服务器程序模型:
import java.io.*;
import java.net.*;
public class Servicer implements Runnable{
Socket s;
public Servicer(Socket s)
{
this.s=s;
}
public void run()
{
try{
InputStream ips=s.getInputStream();
OutputStream ops=s.getOutputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(ips));
DataOutputStream dos=new DataOutputStream(ops);
while(true)
{
String str=br.readLine();
if(str.equalsIgnoreCase("quit"))
break;
String strEcho=(new StringBuffer(str)).toString();
//String strEcho=(new StringBuffer(str).reverse()).toString();
dos.writeBytes(str + "--->" + strEcho + System.getProperty("line.separator"));
}
br.close();
dos.close();
s.close();
}
catch(Exception e){e.printStackTrace();}
}
}
class TcpServer
{
public static void main(String [] args)
{
try{
ServerSocket ss=new ServerSocket(8001);
while(true)
{
Socket s=ss.accept();
new Thread(new Servicer(s)).start();
}
}
catch(Exception e1){e1.printStackTrace();}
}
}
import java.net.*;
import java.io.*;
public class TcpClient {
public static void main(String[] args) {
try{
if(args.length<2)
{
System.out.println("Usage:java Tcpclient serverIP serverPort");
return;
}
Socket s=new Socket(InetAddress.getByName(args[0]),Integer.parseInt(args[1]));
InputStream ips=s.getInputStream();
OutputStream ops=s.getOutputStream();
BufferedReader brkey=new BufferedReader(new InputStreamReader(System.in));
DataOutputStream dos=new DataOutputStream(ops);
BufferedReader brnet=new BufferedReader(new InputStreamReader(ips));
while(true)
{
String strW=brkey.readLine();
dos.writeBytes(strW + System.getProperty("line.separator"));
if (strW.equalsIgnoreCase("quit"))
break;
else
System.out.println(brnet.readLine());
}
dos.close();
brnet.close();
brkey.close();
s.close();
}
catch(Exception e){e.printStackTrace();
}
}
}
发表评论
-
JDK1.5/1.6/1.7之新特性总结
2012-03-28 10:19 780JDK1.5新特性: 1.自动装箱与拆箱: Integer ... -
java线程(2)
2009-09-02 11:30 984四、线程和进程的比较 进程是资源分配的基本单位。所有与 ... -
java线程(1)
2009-09-02 11:29 825线程(thread)是"进程"中某个单一顺 ... -
Java多线程程序设计原理
2009-09-02 11:03 1050多线程是Java语言的一大 ... -
Java多线程编程总结
2009-09-02 11:02 973何时使用多线程技术, ... -
线程与进程(1)
2009-09-02 10:57 948线程和进程的区别: 1、线程是进程的一部分,所以线 ... -
Java修饰词的总结
2009-02-25 09:54 1147Java语言定义了public、pro ... -
Java语法总结 - 数组
2009-01-02 21:42 1071数组(array)是相同类型变量的集合,可以使用共同的名字引用 ... -
JUnit学习
2009-01-02 21:27 1102单元测试是整个测试流 ... -
JUnit 学习笔记
2009-01-02 21:25 1111JUnit 入门 1.JUnit 软件测试在软件投入使用前 ... -
JAVA性能/负载/压力测试工具
2008-12-29 15:13 81301. LoadRunner:支 ... -
Java 关键字
2008-12-29 15:04 910Java 关键字 速查表 访问控制: private 私有的 ... -
单例模式的四种实现
2008-12-29 14:58 8411.Eager//狂汉式 public class Eager ... -
Java多线程技术中所有方法的详细解析
2008-12-26 13:09 667一、run()和start() ... -
细说String/StringBuffer/StringBuilder
2008-12-23 09:12 750StringBuilder 是 JDK5.0 中新 ... -
java集合接口(5)
2008-11-04 10:40 809Java 2集合框架图 集 ... -
java集合接口(4)
2008-11-04 10:34 9896、java.util.TreeMap java.lang ... -
java集合接口(3)
2008-11-04 10:34 8852、java.util.LinkedList List ... -
java集合接口(2)
2008-11-04 10:33 11123.2.2. Comparator接口 若一 ... -
java集合接口(1)
2008-11-04 10:31 11031.Collection 接口 用于表 ...
相关推荐
Java Socket是Java编程语言中实现网络通信的基础组件,它提供了应用程序与网络协议的接口,使得开发者可以构建基于TCP(传输控制协议)或UDP(用户数据报协议)的应用程序。本教程将深入探讨Java Socket编程的核心...
Java Socket是Java编程语言中用于网络通信的核心API,它提供了低级别的、面向连接的、基于TCP/IP协议的网络通信能力。在"Java Socket 视频流转发Socket"这个主题中,我们将深入探讨如何使用Java Socket来处理视频流...
下面,我们将详细介绍如何在Java Socket中使用SSLSocket来传输加密的对象: 1. **创建SSLSocket实例** 首先,我们需要使用`SSLServerSocketFactory`和`SSLContext`来创建一个`SSLSocket`实例。这通常涉及到加载...
Java Socket编程是网络编程的基础,它提供了在两个应用程序之间建立通信连接的能力。在这个场景中,我们讨论的是如何使用Java的Socket来实现文件上传功能,即从客户端将文件发送到服务器,然后保存到服务器的数据库...
Java Socket 是一种网络通信协议,它是Java编程语言中实现客户端-服务器模型的基础。Socket 提供了低级别的、面向连接的、双向通信的网络接口,允许应用程序通过网络进行数据传输。在本示例中,我们将深入探讨Java ...
Java Socket 连接池实现是提高网络应用性能和效率的关键技术之一。在高并发的网络环境中,频繁地创建和销毁Socket连接会导致大量的系统资源浪费,影响整体性能。为了解决这个问题,开发人员通常会使用连接池来管理和...
java socket client 断线重连的简单实现 有什么意见可以提哦
在Java编程语言中,Socket是实现网络通信的基础组件,它为两台计算机之间的通信提供了低级别的接口。在本文中,我们将深入探讨Java Socket客户端代码及其在创建基于Socket的聊天室客户端中的应用。 首先,理解...
java socket处理硬件传过来的16进制数据的工具类,包含大小端转换、byte[]数组转换为16进制的字符串、byte[]转ByteBuffer、16进制字符串转换为byte数组等
Java Socket技术是网络编程中的重要组成部分,主要用于实现两个应用程序之间的通信。在这个场景中,我们讨论的是如何使用Java Socket来实现实时的屏幕监控功能,即服务端能够远程查看客户端的屏幕内容,这样的功能在...
Java Socket网络编程是Java平台中的核心特性,它为开发者提供了在TCP/IP协议下创建网络应用的能力。Socket编程主要用于实现客户端和服务器之间的通信,基于客户机/服务器模型。在这个模型中,服务器端通常处于被动...
下面将详细介绍如何使用Java Socket实现SMTP发送邮件,并涵盖与QQ和Gmail邮箱的兼容性。 首先,为了通过SMTP发送邮件,我们需要理解SMTP的工作流程。SMTP服务器通常使用25号端口进行通信,但在启用SSL或TLS安全连接...
java socket源码解析 java socket源码解析 java socket源码解析 java socket源码解析
在Java网络编程中,Socket是实现客户端与服务器端通信的基础组件。当涉及到通过代理服务器或者负载均衡器(如Nginx)进行TCP转发时,获取用户的真实IP地址可能会变得复杂。在标题“java socket nginx tcp转发 用户...
Java Socket编程是网络编程的基础,它是Java API提供的一种用于实现客户端-服务器通信的接口。在Java中,Socket类和ServerSocket类是进行网络通信的核心组件。这个经典版本可能包含了一系列关于如何有效使用Java ...
Java Socket编程是Java网络编程的基础,它提供了网络通信的能力,使得程序可以与其他计算机上的服务进行交互。在本案例中,我们将关注如何使用Java Socket来实现SMTP(Simple Mail Transfer Protocol)邮件发送,并...
本文将详细介绍 Java Socket 编程的原理、实现方法和应用场景。 一、Java Socket 编程的原理 Java Socket 编程基于 TCP/IP 协议,使用 Socket 类来实现网络通信。 Socket 类是 Java 语言中用于实现网络通信的类,...
Java Socket是Java编程语言中用于网络通信的核心API,它提供了低级别的、面向连接的、基于TCP/IP协议的网络通信服务。本教程将深入探讨Java Socket的相关知识点,旨在帮助开发者理解和掌握如何在Java环境中构建网络...
8. **Java的网络功能与编程**:基础知识—Java的网络功能与编程(1).chm这部分可能介绍了Java的网络编程基础,如URL、URLConnection等,以及如何使用它们进行HTTP请求。 学习Java Socket编程不仅需要理解TCP/IP协议...