概述
- 计算机网络:是指将位置不同计算机,通过通信线路连接起来,在网络操作系统,网络协议…协调下实现网络资源共享。
- 网络编程:在网路通信协议下,实现网络互联的不同的计算机可以进行数据互联。
- 网络编程三要素:
1):端口号
2):IP地址
3):通行协议
关于计算机网络基础知识,例如IP地址的划分,类型,TCP/IP讲解…在我的另外一篇博客有详细讲解:
计算机网络 知识点总结
这篇博客主要讲解网络编程。
InetAddress
public class InetAddress extends Object implements Serializable
此类表示Internet协议(IP)地址。
此类没有构造方法
- 这里说三个方法:
1)
public static InetAddress getAllByName(String host)
throws UnknownHostException
确定主机名称的IP地址。
主机名称可以是机器名称,例如“ java.sun.com ”或其IP地址的文本表示。 如果提供了文字IP地址,则只会检查地址格式的有效性。
2)public String getHostAddress()返回文本显示中的IP地址字符串。
3)public String getHostName()获取此IP地址的主机名。
InetAddress byName = InetAddress.getByName("198.16.1.66");
System.out.println(byName.getHostName());
UDP
-
DatagramPacket
public final class DatagramPacket extends Object
该类表示数据报包。
数据报包用于实现无连接分组传送服务。 仅基于该数据包中包含的信息,每个消息从一台机器路由到另一台机器。 从一台机器发送到另一台机器的多个分组可能会有不同的路由,并且可能以任何顺序到达。 包传送不能保证。
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)
构造用于发送长度的分组数据报包 length具有偏移 ioffset指定主机上到指定的端口号。
参数
buf - 数据包数据。
offset - 分组数据偏移量。
length - 分组数据长度。
address - 目的地址。
port - 目的端口号。 -
DatagramSocket
public class DatagramSocket
extends Object
implements Closeable
此类表示用于发送和接收数据报数据包的套接字。
public DatagramSocket(int port) throws SocketException
构造数据报套接字并将其绑定到本地主机上的指定端口。 套接字将被绑定到wildcard地址,一个由内核选择的IP地址。
public void send(DatagramPacket p) throws IOException
从此套接字发送数据报包。 DatagramPacket包括指示要发送的数据,其长度,远程主机的IP地址和远程主机上的端口号的信息。
public void receive(DatagramPacket p) throws IOException
从此套接字接收数据报包。 当此方法返回时, DatagramPacket的缓冲区将填充接收到的数据。 数据包数据包还包含发送者的IP地址和发件人机器上的端口号。
- UDP发送数据代码:
public static void main(String[] args) throws IOException {
DatagramSocket ds=new DatagramSocket();
InetAddress byName = InetAddress.getByName("198.16.1.66");//IP地址
int port=10086;//端口号
byte []bytes="hahah".getBytes();//要发送的数据
DatagramPacket dp=new DatagramPacket(bytes,bytes.length,byName,port);//打包
ds.send(dp);//发送
ds.close();//关闭
}
- UDP发送数据代码
public static void main(String[] args) throws IOException {
DatagramSocket ds=new DatagramSocket(10086);
byte[]bytes=new byte[1024];
DatagramPacket dp=new DatagramPacket(bytes,1024);
ds.receive(dp);
byte[] data = dp.getData();
String datab=new String(data);
System.out.println(datab);
ds.close();//不许关闭 不然在缓冲流中
}
- UDP通信练习
*
public class UDPsend {
public static void main(String[] args) throws IOException {
DatagramSocket ds=new DatagramSocket();
DatagramPacket dp;
int port=10086;
InetAddress ipaddress=InetAddress.getByName("192.168.1.7");
Scanner in=new Scanner(System.in);
while (true){
System.out.println("输入");
String s=in.nextLine();
if (s.equals("hello")){
break;
}
byte []bytes=s.getBytes();
dp=new DatagramPacket(bytes,bytes.length,ipaddress,port);
ds.send(dp);
}
ds.close();
}
}
public class UDPrecive {
public static void main(String[] args) throws IOException {
int report=10086;
DatagramSocket ds=new DatagramSocket(report);
byte[] bytes=new byte[1024];
DatagramPacket dp=new DatagramPacket(bytes,bytes.length);
while (true){
ds.receive(dp);
byte[] getby=dp.getData();
int len=getby.length;//这里是因为上面new byte[1024],如果有多的空白格子就不让输出了
System.out.println("数据是"+new String(getby,0,len));
}
}
}
TCP
- TCP发送数据
public static void main(String[] args) throws IOException {
int port=10086;
InetAddress ipadd=InetAddress.getByName("192.168.1.7");
Socket socket=new Socket(ipadd,port);
OutputStream bos= socket.getOutputStream();
bos.write("wwww".getBytes());
bos.close();
}
- TCP接受数据
public static void main(String[] args) throws IOException {
int port=10086;
ServerSocket serverSocket=new ServerSocket(port);
Socket socket=serverSocket.accept();
InputStream bis=socket.getInputStream();
int len;
byte []bytes=new byte[1024];
while ((len=bis.read(bytes))!=-1){
System.out.println(new String(bytes));
}
}
- 练习1:服务器端给出反馈
public class TCPcliet {
public static void main(String[] args) throws IOException {
int port =10086;
InetAddress ipadd=InetAddress.getByName("192.168.1.7");
Socket socket=new Socket(ipadd,port);
//传数据
OutputStream ops = socket.getOutputStream();
String senfs="我想连接";
ops.write(senfs.getBytes());
//接受反馈
InputStream ism = socket.getInputStream();
byte []bytes=new byte[1024];
ism.read(bytes);
System.out.println(new String(bytes));
socket.close();
}
}
public class TCPserver {
public static void main(String[] args) throws IOException {
int port=10086;
InetAddress ipadd=InetAddress.getByName("192.168.1.7");
ServerSocket serverSocket=new ServerSocket(port);
//得到接受的套接字
Socket socket =serverSocket.accept();
//读出数据
InputStream ism = socket.getInputStream();
int len;
byte []bytes=new byte[1024];
//阻塞!!!!!
while ((len=ism.read(bytes))!=-1){
System.out.println(new String(bytes));
}
//给出反馈
OutputStream osm = socket.getOutputStream();
osm.write("收到".getBytes());
socket.close();
serverSocket.close();
}
}
发生阻塞代码
- 客户端从文件中读数据传给服务器端
这个练习我会给出两种代码,第一种是错误的,会发生阻塞。
代码一:
public class TCPcliet {
private int port=10086;
private String ip="192.168.1.7";
private Socket socket;
private BufferedWriter bwe;
private BufferedReader bre;
public TCPcliet() {//建立连接
try {
socket=new Socket(ip,port);
startclient(socket);
}catch (IOException e){
e.printStackTrace();
}
}
public void startclient(Socket socket){
try {
//发送数据
bre=new BufferedReader(new FileReader("D://filetest//readw.txt"));
bwe=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String str;
while ((str=bre.readLine())!=null){
bwe.write(str);
bwe.flush();
}
System.out.println("1111");//运行到这给了个标识符
//接受反馈
BufferedReader breserver=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String strk;
while ((strk=breserver.readLine())!=null){
System.out.println(strk);
}
bre.close();
socket.close();
}catch (IOException e){
e.printStackTrace();
}
}
public static void main(String[] args) {
new TCPcliet();
}
}
public class TCPserver {
private int port=10086;
private Socket getsocket;
private ServerSocket serverSocket;
private BufferedReader bre;
private BufferedWriter bwe;
public TCPserver() {
try {//创建连接
ServerSocket serverSocket=new ServerSocket(port);
getsocket=serverSocket.accept();
startserver(getsocket);
}catch (IOException e){
e.printStackTrace();
}
}
public void startserver(Socket socket){
try {
bre=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str;
while ((str=bre.readLine())!=null){
System.out.println(str);
}
System.out.println("222");//运行到这给了个标识符
//给出反馈
bwe=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bwe.write("老子收到了886");
bwe.flush();
bwe.close();
socket.close();
}catch (IOException e){
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
new TCPserver();
}
}
大家注意我服务器端和客户端中间有两个输出
System.out.println(“1111”);//运行到这给了个标识符(客户端)
System.out.println(“222”);//运行到这给了个标识符(服务器端)
上面这段代码输出是这样的:
客户端(TCPclient):
服务器端(TCPserver)
我们发现两个都没有暂停,都停下不动了!而客户端只输出了一个111.
因该是客户端把数据给服务器端而服务器给客户一个反馈,但是我们发现在服务器端并没有输出222,这里是发生了阻塞。
while ((str=bre.readLine())!=null){//阻塞了
System.out.println(str);
}
在这段代码服务器端一直在等着读客户发来的数据,虽然客户端那边发完了(输出111能看出),但是服务器端不知到客户端发送完了,一直在等客户端的数据。而在客户端所以一直收不到服务器端反馈。
解决方法是让服务器端知道什么时候发完了!!
服务器端这样改:
while ((str=bre.readLine())!=null{//阻塞了
if(str.equals("完了")){
break;
}
System.out.println(str);
}
客户端那里只需要在发完数据后在发送一句“完了”。
- 多线程实现
public class TCPcliet {
private int port=10000;
private String IP="192.168.1.7";
private Socket csocket;
private int count;
public TCPcliet() {
try {
csocket =new Socket(IP,port);
start(csocket);
}catch (IOException e){
e.printStackTrace();
}
}
public void start(Socket socket){
try {
while (true){
//发送文件
BufferedReader cbr=
new BufferedReader(new FileReader("D://filetest//readw.txt"));
BufferedWriter cbw=
new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String str;
while ((str=cbr.readLine())!=null){
cbw.write(str);
cbw.newLine();
cbw.flush();
}
socket.shutdownOutput();
System.out.println("222");
//得到反馈
BufferedReader getbr=
new BufferedReader(new InputStreamReader(socket.getInputStream()));
String getstr=getbr.readLine();
System.out.println("收到回复为"+getstr);
}
}catch (IOException e){
e.printStackTrace();
}finally {
try {
socket.close();
}catch (IOException a){
a.printStackTrace();
}
}
}
public void shutdownbuff(){
try {
BufferedWriter stopbuff=
new BufferedWriter(new OutputStreamWriter(csocket.getOutputStream()));
stopbuff.write("老子输入完了,你别阻塞等我了");
}catch (IOException e){
e.printStackTrace();
}
}
public static void main(String[] args) {
new TCPcliet();
}
}
public class TCPserver {
private int port=10000;
private ServerSocket serverSocket;
public TCPserver() {
try {
serverSocket =new ServerSocket(port);
}catch (IOException e){
e.printStackTrace();
}
}
public void startserver(){
try {
while (true){
System.out.println("服务器请求连接");
Socket socket = serverSocket.accept();//这里如果一直未接受会发生阻塞
//创建线程
new Thread(new ThreadServer(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
serverSocket.close();
}catch (IOException a){
a.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException{
new TCPserver().startserver();
}
}
public class ThreadServer implements Runnable {
Socket socket;
public ThreadServer(Socket s) {
this.socket=s;
}
@Override
public void run() {
try {
BufferedReader brsocket=
new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str;
while ((str=brsocket.readLine())!=null){
if (str.equals("老子输入完了,你别阻塞等我了")){
break;
}
System.out.println(str);
}
System.out.println("111");
//给回复
BufferedWriter bw=
new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("俺收到了");
bw.flush();
}catch (IOException e){
e.printStackTrace();
}finally {
try{
socket.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}