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
相关文章
|
3月前
|
存储 监控 安全
单位网络监控软件:Java 技术驱动的高效网络监管体系构建
在数字化办公时代,构建基于Java技术的单位网络监控软件至关重要。该软件能精准监管单位网络活动,保障信息安全,提升工作效率。通过网络流量监测、访问控制及连接状态监控等模块,实现高效网络监管,确保网络稳定、安全、高效运行。
96 11
|
16天前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
66 23
|
1月前
|
安全 网络协议 Java
Java网络编程封装
Java网络编程封装原理旨在隐藏底层通信细节,提供简洁、安全的高层接口。通过简化开发、提高安全性和增强可维护性,封装使开发者能更高效地进行网络应用开发。常见的封装层次包括套接字层(如Socket和ServerSocket类),以及更高层次的HTTP请求封装(如RestTemplate)。示例代码展示了如何使用RestTemplate简化HTTP请求的发送与处理,确保代码清晰易维护。
|
1月前
|
缓存 网络协议 Java
JAVA网络IO之NIO/BIO
本文介绍了Java网络编程的基础与历史演进,重点阐述了IO和Socket的概念。Java的IO分为设备和接口两部分,通过流、字节、字符等方式实现与外部的交互。
|
2月前
|
Java 物联网 定位技术
Java socket获取gps定位
通过Java Socket编程获取GPS定位信息可以实现实时的地理位置跟踪。本文介绍了如何搭建Socket服务器、解析GPS数据以及实现客户端发送GPS数据的流程。希望这篇文章能为开发者提供清晰的指导,帮助构建高效的GPS定位系统。
61 7
|
4月前
|
网络协议 Java 物联网
Java网络编程知识点
Java网络编程知识点
88 13
|
4月前
|
数据采集 Java API
java怎么设置代理ip:简单步骤,实现高效网络请求
本文介绍了在Java中设置代理IP的方法,包括使用系统属性设置HTTP和HTTPS代理、在URL连接中设置代理、设置身份验证代理,以及使用第三方库如Apache HttpClient进行更复杂的代理配置。这些方法有助于提高网络请求的安全性和灵活性。
163 0
|
8月前
|
安全 Java Linux
(七)Java网络编程-IO模型篇之从BIO、NIO、AIO到内核select、epoll剖析!
IO(Input/Output)方面的基本知识,相信大家都不陌生,毕竟这也是在学习编程基础时就已经接触过的内容,但最初的IO教学大多数是停留在最基本的BIO,而并未对于NIO、AIO、多路复用等的高级内容进行详细讲述,但这些却是大部分高性能技术的底层核心,因此本文则准备围绕着IO知识进行展开。
239 1
|
8月前
|
Java 大数据
如何在Java中进行网络编程:Socket与NIO
如何在Java中进行网络编程:Socket与NIO
|
10月前
|
监控 Java 开发者
深入理解 Java 网络编程和 NIO
【4月更文挑战第19天】Java网络编程基于Socket,但NIO(非阻塞I/O)提升了效率和性能。NIO特点是非阻塞模式、选择器机制和缓冲区,适合高并发场景。使用NIO涉及通道、选择器和事件处理,优点是高并发、资源利用率和可扩展性,但复杂度、错误处理和性能调优是挑战。开发者应根据需求选择是否使用NIO,并深入理解其原理。
105 1

热门文章

最新文章