Java网络编程之简单Socket和ServerSocket

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介:

常用基本类

InetAddress是java中表示IP的类。主要用于Socket,ServerSocket,URL,DatagramSocket等
 创建InetAddress用三个静态方法
getByName(String hostname)throws UnknownHostException
 getAllByName(String hostname) throws UnknownHostException
 getLocalHost() throws UnknownHostException
 使用这三个静态方法创建InetAddress的时候,除了使用getByName中传递ip地址外(如果使用getByName传递一个ip会首先创建一个InetAddress不管是否存在,当显示的调用getHostName或者toString的时候才会进行网络连接),都会首先进行网络连接,会根据主机名去连接DNS服务器,来查找对应的主机名和ip,一定要捕获异常处理。
 对于已经创建成功的InetAddress可以获取基本属性,getAddress()返回一个字节数组,可以利用
 int unsigned=signByte<0? signByte+256: signByte转换为int。也可以利用它的长度来判断是IPv4或者IPv6。
 两个InetAddress对象equals的条件是具有相同的IP,不管主机名是否相等
 toString的表现形式为:hostname/ip
URL类,是一个final类,使用的是策略设计模式,协议就是策略。
 构造URL的基本方法URL url=new URL("http://www.baidu.com"),如果创建未支持的协议的URL则会出现MalformedURLException异常。
 URL主要由协议、授权机构、路径、片段标示符和查询字符串表示。
 openStream():连接URL所指向的资源,执行客户端与服务器之间的握手,返回一个可读取的数据
 openConnection():打开指定的URL的socket,返回一个URLConnection(表示一个打开网络资源的连接)
 getContent()
 在利用URL进行发送数据的时候,主要URL中只需出现ASCII中的固定子集,未出现的必须进行编码,利用URLEncoder来编码,要对每一部分编码,再用URLDecoder解析编码
URI类是纯粹的关于资源的标识和URI的解析,它没有网络获取功能,主要用于对于URL进行分析。

基于TCP的Socket编程(Socket和ServerSocket)
客户端Socket建立步骤:
1 利用构造函数创建一个新Socket
2 Socket尝试连接远程主机(在构造函数创建后,该socket就会自动连接远程主机)
3 一旦建立连接,此socket就会进行输入流和输出流操作。连接是全双工,双方可同时发送接受数据
4 当数据传输完毕后,一端就或两端就会关闭连接。HTTP1.0,要求每次请求得到服务器响应后就关闭连接。
创建Socket基本方法Socket socket=new Socket("www.ttt.com",80);一定要捕获异常,当主机名不存在的时候,抛出UnknownHostException异常,其他情况会抛出IOException,可以用来测试某一些端口是否可利用。
 获取Socket的输入流,socket.getInputStream();可以通过这个来获取服务器返回的结果,在其调用read的时候会一直阻塞着。一般均要将其链接到过滤器流或者阅读器。
 写入Socket的输出流,socket.getOutputStream();向服务器发送数据,但是这里务必要每次写入后加上out.write("\r\n\r\n"),out.flush(),关闭输出流。对于每行都要加上"\r\n"
 判断一个socket当前是否打开,需要用如下方式:
 isClose返回false仅在已经被关闭或者从未打开的时候
 isConnected表示曾经打开过
boolean connected=socket.isConnected()&&! socket.isClosed();
SocketAddress类,主要用于存放暂时的Socket连接信息,将上次的连接保存后,下次直接利用connect来连接。创建一个SocketAddress,可以通过其子类InetSocketAddress来创建,
InetSocketAddress,此类实现 IP 套接字地址(IP 地址 + 端口号),
它还可以是一个对(主机名 + 端口号)。
InetSocketAddress(String hostname, int port)  ;根据字符串指定的主机名来创建

ServerSocket建立步骤
1 使用ServerSocket()构造函数来在某个端口创建一个ServerSocket
2 ServerSocket使用其accept()监听此端口的所有入站请求。在没有请求的时候,该accept方法会一直阻塞,它会使得整个程序停止执行并且等待,直到有客户端尝试进行连接,此时就会返回一个连接客户端和服务器的Socket对象
3 调用输入输出流类型
4 关闭该Socket对象
5 继续等待
 创建一个ServerSocket的基本方法ServerSocket server=new ServerSocket(1888);会抛出IOException和BindException的异常。
 测试一个ServerSocket是否打开利用 ss.isBound()&& !ss.isClosed()来判断。

简单Socket和Server连接测试
客户端Socket
package com.client;

import java.io.IOException;
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;

public class FirstClient {
public static void main(String[] args) {
// TODO Auto-generated method stub
   Socket client= null;
try{
     client= new Socket( "localhost",6666);
     InputStream in=client.getInputStream();

     OutputStream outs=client.getOutputStream();
     BufferedOutputStream buffs= new BufferedOutputStream(outs);
     Writer out= new OutputStreamWriter(buffs);
     out.write( "hello===");
//out.flush();
     out.close();
//一定要关闭输出流,否则它会一直占用该端口以及资源
   } catch(UnknownHostException e)
   {
     e.printStackTrace();
   } catch(IOException e)
   {
     e.printStackTrace();
   }
 }
}
服务器端Socket
package com.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class FirstServer {
public static void main(String[] args) {
// TODO Auto-generated method stub

try {
     ServerSocket server =  new ServerSocket(6666);
while ( true) {
       Socket client =  null;
try {
         client = server.accept();

         InputStream ins = client.getInputStream();
         BufferedReader read =  new BufferedReader(
new InputStreamReader(ins));
         String res = read.readLine();
         read.close();
         System.out.println( "client request:" + res);
       }  catch (IOException e) {
         e.printStackTrace();
       }  finally {
try {
if (client !=  null)
             client.close();
         }  catch (IOException e) {
           e.printStackTrace();
         }
       }
     }
   }  catch (IOException e) {
     e.printStackTrace();
   }
 }
}

客户端服务器端发送和接受流
不管是客户端Socket处理流或者服务器端获得Socket处理流,不要随便关闭它们获得的输入流和输出流,因为关闭这些流的时候会将该Socket也给关闭了,这是由于流在关闭的时候会释放它所占有的资源,如句柄或端口。
输入流处理
输入流处理主要就是处理来自socket发送的请求信息,不管是客户端还是服务器端都需要先利用getInputstream获得一个socket传输的流。
下面是输入流中最关键的部分就是分析请求的头部,主要是在服务器端
   Socket socket= null;
   BufferedReader netwin= null; //一般在网络中不用这种方式,仅仅一般测试用
try{
     socket= new Socket( "localhost",2222);

     String header= "HTTP/1.0 200 OK\r\n"+
"Server:Apache 7.0\r\n"+
"Content-length:"+107+ "\r\n"+
"Content-type: text/html\r\n\r\n";


//输出流
     OutputStream outfile= new BufferedOutputStream(socket.getOutputStream());
     Writer write= new OutputStreamWriter(outfile);
//输入流
     InputStream inputstream=socket.getInputStream();
     BufferedInputStream in= new BufferedInputStream(inputstream);
     InputStreamReader inr= new InputStreamReader(in);


//对于http请求的需要先判断是否是http协议
//判断请求是否是http协议主要就是处理输入流中的第一行
//第一种处理解析请求头部
     StringBuffer request1= new StringBuffer(100);
while( true)
     {
int c=in.read();
if(c=='\r' || c=='\n' || c==-1)
break;
       request1.append(( char)c);
     }
     String requestHeader1=request1.toString();
if(requestHeader1.indexOf( "HTTP/")!=-1)
       write.write(header);
     write.flush();
     write.close();


//第二种处理解析请求头部
     StringBuffer request2= new StringBuffer(100);
while( true)
     {
int c=in.read();
if(c=='\r' || c=='\n' || c==-1)
break;
       request2.append(( char)c);
     }
//截取第一行每一部分
//一般http请求格式GET /index.html HTTP/1.0
     String requestHeader2=request2.toString();
int firstSpace=requestHeader2.indexOf(' ');
int secondSpace=requestHeader2.indexOf(' ', firstSpace+1);
     String fileName=requestHeader2.substring(firstSpace+1,secondSpace);
if(requestHeader1.indexOf( "HTTP/")!=-1)
     {
       write.write(header);
       write.flush();
       write.close();
     }


//第三种处理解析请求头部
     StringBuffer request3= new StringBuffer(100);
while( true)
     {
int c=in.read();
if(c=='\r' || c=='\n' || c==-1)
break;
       request3.append(( char)c);
     }
//截取第一行每一部分
//一般http请求格式GET /index.html HTTP/1.0
     String requestHeader3=request3.toString();
//使用默认分隔符,包括空白字符,制表符,换行符,回车符,换页符
     StringTokenizer st= new StringTokenizer(requestHeader3);
     String method=st.nextToken();
     String version="";
     String filename=st.nextToken();
     String httpT="";
if(st.hasMoreTokens())
       httpT=st.nextToken();
if(httpT.indexOf( "HTTP/")!=-1)
     {
       write.write(header);
       write.flush();
       write.close();
     }

   } catch(IOException e)
   {
     e.printStackTrace();
   }

输出流处理
在利用http发送数据的时候,每一行都应该由\r\n结束,一般不要使用pringln这种,因为java在linux中换行是以\n结束,windows下换行是以\r\n。 但是在利用http进行请求与响应的过程中,两个都必须每次写入后最后要写入\r\n\r\n,再要将输出流flush以及关闭该输出流。如果不是用http请求一般只需要在每行加入\r\n
不管是客户端还是服务器端要发送流,就必须先getOutputStream来获取一个写入流,用于发送到另一端的Socket中。一般均要放到输出流或者书写器中。
输出流是以字节为单位写的,这样会加快数据的传输速度,便于传输。
书写器是以字符为单位写的,方便写入数据。
基本的输出流写入方式
       socket= new Socket( "localhost",2222);
       OutputStream outs=socket.getOutputStream();
//利用缓冲来
       BufferedOutputStream buffer= new BufferedOutputStream(outs);
       writer= new OutputStreamWriter(buffer); 

//在写入的过程中每一行必须要以\r\n结束
       writer.write( "hello");

//这里是一般请求则,只需要加上\r\n即可
       writer.write( "\r\n");
//当是http请求的时候需要这样处理,请求最后加上\r\n
//writer.write("GET /index.html http/1.0 ")
//writer.write("\r\n\r\n")
       writer.flush();
       writer.close();
当是对于http请求进行响应的时候就需要写入MIME首部,且返回文件的时候,该代码实例基本功能是传输客户端请求的页面,并且根据http协议传送首部,错误处理
//这里写入的只是一些小型文件的处理
     InputStream in= new FileInputStream( "f:\\t.txt");
     ByteArrayOutputStream out= new ByteArrayOutputStream();
int b;
while((b=in.read())!=-1)out.write(b);
byte[] data=out.toByteArray();

//下面的是读取大文件处理的方式
//      File file=new File("f:\\t.txt");
//      DataInputStream fis=new DataInputStream(
//          new BufferedInputStream(new FileInputStream(file)));
//      //存放数据
//      byte[] data=new byte[(int)file.length()];
//      fis.readFully(data);//将文件读入到字节数组中
//      fis.close();//直接在输出流中加入该data


//编写MIME首部的格式
     String header= "HTTP/1.0 200 OK\r\n"+
"Server:Apache 7.0\r\n"+
"Content-length:"+data.length+ "\r\n"+
"Content-type: text/html\r\n\r\n";

//开始写入输出流
     socket= new Socket( "localhost",2222);
//利用缓冲来
     OutputStream outfile= new BufferedOutputStream(socket.getOutputStream());
     Writer write= new OutputStreamWriter(outfile);
//这里一般要先判断是否是http协议,
//if(request.indexof("HTTP")!=-1)
//write.write(header);
     write.flush();
     write.close();

//发送文件一般直接用输出流,不要用书写器
     outfile.write(data);
     outfile.flush();
     outfile.close();

//当文件不存在的时候
//这里还是要判断是否是http协议,如果是先要添加MIME首部
       write.write( "HTTP/1.0 404 File Not Found\r\n");
       write.write( "Server:Apache 7.0\r\n");
       write.write( "Content-type:text/html");
       write.write( "\r\n\r\n");

//当不是http协议还要输出显示
       write.write( "<HTML>\r\n");
       write.write( "<HEAD><TITLE>File Not Found</TITLE></HEAD>\r\n");
       write.write( "<BODY>HTTP ERROR 404 :File Not Found\r\n");
       write.write( "</BODY></HTML>\r\n");
       write.flush();
       write.close();


本文转自 zhao_xiao_long 51CTO博客,原文链接:http://blog.51cto.com/computerdragon/1192073
相关文章
|
12天前
|
人工智能 Java 物联网
JAVA网络编程的未来:URL与URLConnection的无限可能,你准备好了吗?
随着技术的发展和互联网的普及,JAVA网络编程迎来新的机遇。本文通过案例分析,探讨URL与URLConnection在智能API调用和实时数据流处理中的关键作用,展望其未来趋势和潜力。
35 7
|
12天前
|
安全 Java API
深入探索Java网络编程中的HttpURLConnection:从基础到进阶
本文介绍了Java网络编程中HttpURLConnection的高级特性,包括灵活使用不同HTTP方法、处理重定向、管理Cookie、优化安全性以及处理大文件上传和下载。通过解答五个常见问题,帮助开发者提升网络编程的效率和安全性。
|
12天前
|
JSON 安全 算法
JAVA网络编程中的URL与URLConnection:那些你不知道的秘密!
在Java网络编程中,URL与URLConnection是连接网络资源的两大基石。本文通过问题解答形式,揭示了它们的深层秘密,包括特殊字符处理、请求头设置、响应体读取、支持的HTTP方法及性能优化技巧,帮助你掌握高效、安全的网络编程技能。
40 9
|
12天前
|
JSON Java API
JAVA网络编程新纪元:URL与URLConnection的神级运用,你真的会了吗?
本文深入探讨了Java网络编程中URL和URLConnection的高级应用,通过示例代码展示了如何解析URL、发送GET请求并读取响应内容。文章挑战了传统认知,帮助读者更好地理解和运用这两个基础组件,提升网络编程能力。
34 5
|
12天前
|
Kubernetes 网络协议 Python
Python网络编程:从Socket到Web应用
在信息时代,网络编程是软件开发的重要组成部分。Python作为多用途编程语言,提供了从Socket编程到Web应用开发的强大支持。本文将从基础的Socket编程入手,逐步深入到复杂的Web应用开发,涵盖Flask、Django等框架的应用,以及异步Web编程和微服务架构。通过本文,读者将全面了解Python在网络编程领域的应用。
14 1
|
1月前
|
Java 流计算
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
35 1
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
|
15天前
|
Java
[Java]Socket套接字(网络编程入门)
本文介绍了基于Java Socket实现的一对一和多对多聊天模式。一对一模式通过Server和Client类实现简单的消息收发;多对多模式则通过Server类维护客户端集合,并使用多线程实现实时消息广播。文章旨在帮助读者理解Socket的基本原理和应用。
15 1
|
4月前
|
网络协议 安全 Java
Java中的网络编程:Socket编程详解
Java中的网络编程:Socket编程详解
|
4月前
|
Java API 网络安全
Java网络编程入门
Java网络编程入门
|
4月前
|
网络协议 安全 Java
Java中的网络编程:Socket编程详解
Java中的网络编程:Socket编程详解
下一篇
无影云桌面