一:端口号范围 0~~~65535之间,0~~1023之间的端口数是用于一些之名网络服务的应用。
注意的事情是127.0.0.1是本地回路ip地址。这个端口并不需要通过网卡。直接就可以访问本机。其中UDP与TCP传输协议,是比较主要的传输协议。
TCP,输出控制协议(Transmission Control Protocol),是面向连接的信息协议。
UDP,用户是举报协议(User Datagram Protocol),是无连接通信协议。
TCP,UDP的数据格式
在这个格式中协议类型来区分是UDP还是TCP。
Socket是网络驱动层提供给应用程序编程的接口和一种机制。Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的ip和prot。
Socket与驱动程序的流程:
发送数据过程理解,应用程序创建Socket对象后,应用程序调用bind方法,绑定驱动程序(绑定的时候主要是把ip和端口号通知驱动程序)。然后应用程序,将数据发送到Socket,这个时候驱动程序会把Socket里面的数据处理后,通过网卡发送到指定的ip地址的机器上。
接受数据的过程,应用程序创建Socket,然后将要监听的ip和端口告诉驱动程
DatagramSocket构造函数
Public new DatagramSocket();
Public new DatagramSocket(int prot);
Public new DatagramSocket(int prot,InetAddress laddr);
Send(DatagremPacket pt);
Receive(DatagremPacket pt);
DatagramPacket 数据集装箱类
Public new DatagramPacket(Byte [] bytes, int length);
new DatagramPacket(Byte[]bytes,int length,InetAddress laddr,int prot)
DatagramPacket对象有getInetAddress()和getProt()方法.来获得发送的ip和端口号。
InetAddress 对象,在计算机中ip地址是通过这个对象来表示的,其中我们经常使用一个’192.168.1.1’这样的字符串来表示,InetAddress对象有一个getByName的静态方法来通过这样的ip地址放回一个InetAddress对象。同时一个InetAddress对象同样可以使用getHostAddress方法来获得这样的一个ip地址。
UDP例子:
public class UDPreceive {
public static void main(String[] args) throws Exception {
while(true)
{
DatagramSocket datagramSocket=new DatagramSocket(3000);
byte[] b=new byte[1024];
DatagramPacket packet=new DatagramPacket(b,1024 );
datagramSocket.receive(packet);
String str=new String(packet.getData(),0,packet.getLength());
System.out.println(str);
System.out.println(packet.getAddress().getHostAddress() + "~~~~~~~~"
+ packet.getPort());
datagramSocket.close();
}
}
}
上面是接收端
package com.udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPsend { public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket();
String str = "IT牛人";
socket.send(new DatagramPacket(str.getBytes(), str.getBytes().length,
InetAddress.getByName("192.168.18.4"), 3000));
socket.close();
}
}
三package awt.udp;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.List;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* @author tianzhw
* 更具老师的讲解,我对这个UDP网络聊天室的理解,全部在注释里面了,UDP可以理解为一个不安全的网络传输协议。
* 它只是负责传输,至于在接收端是否可以接受的得到,它并不做判断
*/
public class Chat extends Frame {
List list = new List(6);//这个用的不是java.util.List包,而是窗体java.awt.List
TextField fieldIP = new TextField(15);
TextField fieldData = new TextField(20);
//上面两个大家都明白,就是定义了两个文本输入框 并同时定义了其名字
DatagramSocket socket = null;
//因为Socket这个变量要在全局下使用,所以定义在这里。
public Chat() {
this.add(list, "Center");
Panel panel = new Panel();
this.add(panel, "South");
panel.setLayout(new BorderLayout());
panel.add(fieldIP, "West");
panel.add(fieldData, "East");
//Panel放在窗体内,同时将我们副本框还有我们装聊天消息放到panel里面
try {
socket = new DatagramSocket(3000);
//这个是构造一个对象,其中参数的意思。我个人理解为在3000端口创建一个监听,随时准备接受来之3000端口的信息
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
/*
* 因为在Socket中 receive方法,是接受一个UDP的信息。如果,没有一个条消息,这个方法会阻塞在那里。一等到有信息来。
* 所以如果我们写在一个进程中,程序在运行到这个位置的时候就会阻塞在这里没有办法进行下去,所以我们,有启动了另一个线程
*/
new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
byte[] b = new byte[1024];
DatagramPacket pack = new DatagramPacket(b, b.length);
while (true) {
try {
socket.receive(pack);
list.add(new String(b, 0, pack.getLength())
+ "~~~~~~~~~~~来至于" + pack.getAddress() + "的"
+ pack.getPort() + "端口", 0);
//其中要特别理解的是,getLength方法,则个方法会返回,我们在3000端口中接受的字节数组的长度。
} catch (IOException e) {
if (socket.isClosed()) {
} else
e.printStackTrace();
}}}}).start();
fieldData.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
byte[] by;
by = fieldData.getText().getBytes();
socket.send(new DatagramPacket(fieldData.getText()
.getBytes(), fieldData.getText().getBytes().length,
InetAddress.getByName(fieldIP.getText()), 3000));
//send方法的四个参数,第一个是要传送的字节数组,这里面就是我们要输入文本框里面的数据,
// 第二个输出的长度,后面一个要发送的ip地址,最后就是要发送的端口
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
fieldData.setText("");}});
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
socket.close();//在关闭程序的时候 结束Socket
dispose();
System.exit(0);
}});
}
}
四:
package com.tcp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPserver {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8001);//创建一个服务器端Socket,在指定的端口8001上创建
Socket socket = serverSocket.accept();//accpet这个方法可以获得一个连接的本服务器的socket对象。
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
String str = "欢迎你的到来,我是服务器";
out.write(str.getBytes(), 0, str.getBytes().length);
byte[] b = new byte[1024];
BufferedReader reader=new BufferedReader(new InputStreamReader(in));
System.out.println(reader.readLine());;
reader.close();
out.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
五:
过滤流和包装类
比如说DataOutPutStream类,他可以去解决各种去数据的操作。
BufferedInputStream与BufferedOutputStream类是java的缓冲流,缓冲流为I/o流增加了内存的缓冲区,增加缓冲区的两个基本的目的:
允许java程序的一次不智操作的一个字节,这样提高了程序的性能。
由于有了缓冲区,是的在流上执行的skip、mark和reset方法都成为了可能。
格式化说出 :就是将一个数据安装字符串的格式输出。
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
OutputStream out = new FileOutputStream("tian.txt");
BufferedOutputStream bou = new BufferedOutputStream(out);
DataOutputStream dot = new DataOutputStream(bou);
dot
.writeUTF("为I/o流增加了内存的缓冲区,增加缓冲区的两个基本的目的:允许java程序的一次不智操作的一个字节,这样提高了程序的性能。由于有了缓冲区,是的在流上执行的skip、mark和reset方法都成为了可能。");
dot.close();
InputStream in = new FileInputStream("tian.txt");
BufferedInputStream buin = new BufferedInputStream(in);
DataInputStream din = new DataInputStream(buin);
String str = din.readUTF();
din.close();
System.out.println(str);
}