浅谈网络编程技术(TCP、UDP、HTTP)
来源:互联网 发布:linux 文件内容替换 编辑:程序博客网 时间:2024/05/21 07:47
在介绍这三种编程技术之前,先说一下网络编程的三要素:
- IP地址:网络中计算机的唯一标识
- 端口:正在运行程序的标识(有效的端口区间在0~65535之间,其中0~1024系统使用或保留端口)
- 协议:通信的规则
举一个简单的例子:
我要和某人说话,这个步骤流程是什么?
首先,我要找到说话的对象(通过IP地址找到的);
然后,开始对她说话,怎么说,要对着耳朵说(端口);
说了什么,I love you,她好像听不懂英文,这时候我没必要讲英文了,说汉语就好,(协议)
*
1、UDP编程*
特点如下:
- 把数据打包
- 数据有限制
- 不建立连接
- 速度快
- 不可靠
然后我们通过代码来了解UDP编程:
这段代码是UDP服务端的代码;public class UdpServer { public static final int PORT = 30000; // 定义每个数据报的最大大小为4K private static final int DATA_LEN = 4096; // 定义接收网络数据的字节数组 byte[] inBuff = new byte[DATA_LEN]; // 以指定字节数组创建准备接受数据的DatagramPacket对象 /** * 可存储4K数据的数据报文 */ private DatagramPacket inPacket = new DatagramPacket(inBuff, inBuff.length); // 定义一个用于发送的DatagramPacket对象 private DatagramPacket outPacket; // 定义一个字符串数组,服务器发送该数组的的元素 String[] books = new String[] { "疯狂Java讲义", "轻量级Java EE企业应用实战", "疯狂Android讲义", "疯狂Ajax讲义" }; public void init() throws IOException { try ( // 创建DatagramSocket对象 DatagramSocket socket = new DatagramSocket(PORT)) { // 采用循环接受数据 for (int i = 0; i < 1000; i++) { // 读取Socket中的数据,读到的数据放入inPacket封装的数组里。 socket.receive(inPacket); // 判断inPacket.getData()和inBuff是否是同一个数组 System.out.println(inBuff == inPacket.getData());// ----- // 将接收到的内容转成字符串后输出 System.out.println(new String(inBuff, 0, inPacket.getLength())); // 从字符串数组中取出一个元素作为发送的数据 byte[] sendData = books[i % 4].getBytes(); // 以指定字节数组作为发送数据、以刚接受到的DatagramPacket的 // 源SocketAddress作为目标SocketAddress创建DatagramPacket。 outPacket = new DatagramPacket(sendData, sendData.length, inPacket.getSocketAddress()); // 发送数据 socket.send(outPacket); } } } public static void main(String[] args) throws IOException { new UdpServer().init(); }}
这是客户端的代码:
public class UdpClient { // 定义发送数据报的目的地 public static final int DEST_PORT = 30000; public static final String DEST_IP = "127.0.0.1";//测试本机 // 定义每个数据报的最大大小为4K private static final int DATA_LEN = 4096; // 定义接收网络数据的字节数组 byte[] inBuff = new byte[DATA_LEN]; // 以指定字节数组创建准备接受数据的DatagramPacket对象 private DatagramPacket inPacket = new DatagramPacket(inBuff, inBuff.length); // 定义一个用于发送的DatagramPacket对象 private DatagramPacket outPacket = null; public void init() throws IOException { try (DatagramSocket socket = new DatagramSocket()) { // 初始化发送用的DatagramSocket,它包含一个长度为0的字节数组 outPacket = new DatagramPacket(new byte[0], 0, InetAddress.getByName(DEST_IP), DEST_PORT); // 创建键盘输入流 Scanner scan = new Scanner(System.in); // 不断读取键盘输入 while (scan.hasNextLine()) { // 将键盘输入的一行字符串转换字节数组 byte[] buff = scan.nextLine().getBytes(); // 设置发送用的DatagramPacket里的字节数据 outPacket.setData(buff); // 发送数据报 socket.send(outPacket); // 读取Socket中的数据,读到的数据放在inPacket所封装的字节数组里。 socket.receive(inPacket); System.out.println(new String(inBuff, 0, inPacket.getLength())); } } } public static void main(String[] args) throws IOException { new UdpClient().init(); }}
2、TCP协议
特点如下:
- 需要建立连接通道
- 数据无限制
- 速度慢
可靠
这是服务端代码:
public class Server { public static void main(String[] args) throws IOException { // 8888监听的端口号 ServerSocket ss = new ServerSocket(8888); boolean isFlag = true; while(isFlag) { // 与客户端对应的socket, 阻塞 Socket socket = ss.accept(); PrintWriter pw = new PrintWriter(socket.getOutputStream()); pw.write("服务端"); pw.close(); } if (!ss.isClosed()) { ss.close(); } }}
这是客户端代码
public class Client { public static void main(String[] args) throws UnknownHostException, IOException { // 10.50.8.40 Socket socket = new Socket("127.0.0.1", 8890);// System.out.println(br.readLine());// br.close(); new Thread(new ClientThread(socket)).start(); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line = null;// PrintWriter pw = new PrintWriter(socket.getOutputStream()); PrintStream ps = new PrintStream(socket.getOutputStream()); while ((line = br.readLine()) != null) { // 将用户的键盘输入内容写入Socket对应的输出流// pw.println(line);// pw.flush(); System.out.println(line + "----------"); ps.print(line); ps.flush(); }// PrintWriter pw = new PrintWriter(socket.getOutputStream());// pw.println("zhangtao");// pw.flush();// pw.close(); }}
其中类ClientThread代码如下:
package com.gb.android.tcp.chat;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.Socket;public class ClientThread implements Runnable { Socket socket; BufferedReader br; public ClientThread(Socket socket) throws IOException { this.socket = socket; br = new BufferedReader(new InputStreamReader(socket.getInputStream())); } @Override public void run() { String line = null; try { while ((line = br.readLine()) != null) { System.out.println(line); }// br.close(); } catch (IOException e) { e.printStackTrace(); } }}
3、HTTP编程
http网络编程有两种,分别是HttpURLConnection和HttpClient:
首先是HttpURLConnection的用法:
一般只需要new出一个URL对象,并出入目标的网络地址,然后调用一下openConnection()方法即可,如下所示:
URL url=new URL("http://www.baidu.com");HttpURLConnection connection=(HttpURLConnection)url.openConnection();
得到HttpURLConnection的实例之后,我们就可以设置一下HTTP请求所使用的方法。常用的方法主要有两个,GET和POST。GET表示希望从服务区哪里了获取数据,而POST则表示希望提交数据给服务器。写法如下:
connection.setRequestMethod("GET");
接下来就可以进行一些自由的定制了,比如设置连接超时、读取超时的毫秒数,以及服务器希望得到的一些消息头等。这部分内容根据自己的实际情况进行编写,实例写法如下:
connection.setConnectTimeOut(8000);connection.setReadTimeOut(8000);
之后调用getInputStream()方法就可以获取到服务器返回的输入流了,剩下的任务就是对流的读取,如下:
InputStream in =connection.getInputStream();
最后就可以调用disconnect()方法将这个HTTP连接关闭掉,如下:
connection.disconnect();
根据上面的步骤,很容易写出一个获取网络数据的代码:
开辟了一个线程处理耗时的网络操作
public class HttpClient { public void getInfo() { new Thread(new Runnable() { public void run() { URL url; HttpURLConnection connection = null; try { url = new URL("http://www.baidu.com"); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(8000); connection.setConnectTimeout(8000); InputStream in = (InputStream) connection.getInputStream(); BufferedReader reader = new BufferedReader( new InputStreamReader(in)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (connection != null) { connection.disconnect(); } } } }).start(); }}
HttpClient是Apache提供的HTTP网络访问接口,从一开始的时候就被引入到了androidAPI中,他可以完成和HttpURLConnection巨虎一模一样的效果,但两者也有很大的差别:
HttpClient是一个接口,接口无法创建实例,他会创建DefaultHttpClient的实例,如下:
HttpClient HttpClient=new DefaultHttpClient();
`接着可以创建一个GET请求,就可以创建一个HttpGet对象,并传入网络地址然后调用HttpClient的execute()方法即可:
HttpGet httpGet=new HttpGet(“http://www.baidu.com”);httpClient.execute(httpClient);
然而POST’请求会比GET请求复杂一些,需要创建一个HttpPost对象,并传入目标网路的地址,如下:
HttpPost httpPost=new HttpPost(“http://www.baidu.com”);
然后通过一个NameValuePair集合来存放带待提交的参数,并将这个参数传入到一个UrlEncodedFormEntity中,然后调用HttpPost的setEntity()方法将构建好的UrlEncodedFormEntity传入,如下:
List<NameValuePair> params= new ArrayList<NameValuePair>();params.add(new BasicNameValuePair("username","admin"));params.add(new BasicNameValuePair("password","123456"));UrlEncodedFormEntity entity=new UrlEncodedFormEntity(params,"utf-8");httpPost.setEntity(entity);
接下来和HttpGet是一样的,调用HttpClient的execute()方法,并传入HttpPost对象即可:
httpClient.execute();
执行execute()方法之后就会返回一个HttpResponse对象,服务器返回的所有信息都在这里,通常会先取出服务器的返回状态码,如果是200说明请求和响应是成功的 。如下所示:
if(httpResponse.getStatusLine().getStatusCode()==200){//请求和响应成功!}
接下来取出内容可一个调用个getEntity()方法获取到一个HttpEntity实例,然后再用EntityUtils.toString()这个静态方法将HttpEntity转换成字符串;如下:
HttpEntity entity=httpResponse.getEntity();String response=EntityUtils.toString(entity);
注意乱码问题,如果服务器端返回的数据是带有中文的,直接调用EntityUtils.toString()方法转换会出现乱码,这时候转换的时候将字符集指定成utf-8就可以了,如下:
String response =EntityUtils.toString(entity,“utf-8”);
根据上面的步骤很容易写出一个网络请求数据的代码:
package http;import javax.xml.ws.Response;public class HttpClient { public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { HttpClient httpClient=new DefaultHttpClient(); HttpGet httpGet=new HttpGet("http://www.baidu.com"); HttpResponse httpResponse= httpClient.execute(); if(httpResponse.getStatusLine().getStatusCode()==200){ //请求和响应成功! HttpEntity entity=httpResponse.getEntity(); String response =EntityUtils.toString(entity,“utf-8”); String info=response.toString(); } } }).start(); }}
- 浅谈网络编程技术(TCP、UDP、HTTP)
- 浅谈HTTP,TCP,UDP
- iOS 网络编程 TCP/UDP HTTP
- android 网络编程Udp、Tcp、Http Socket
- TCP/UDP/SOCKET/HTTP浅谈
- android 之浅谈UDP与TCP网络编程
- TCP网络编程&&UDP
- 网络编程 UDP TCP
- 网络编程(TCP/UDP)
- 网络编程-UDP-TCP
- TCP/UDP网络编程
- 网络编程TCP/UDP
- 网络编程(tcp、udp)
- iOS经典讲解之网络编程 TCP/UDP HTTP
- 网络编程--Socket、TCP/IP、UDP、Http之间的关系
- 关于cocos2dx网络编程http,udp,tcp,socket
- iOS经典讲解之网络编程 TCP/UDP HTTP
- Windows网络编程(TCP/UDP)
- UART串口通信
- 3°、6°带高斯-克吕格投影
- 【java】String类常见面试题
- 12.23面试
- Ubuntu14.04安装Cmake3.2.2
- 浅谈网络编程技术(TCP、UDP、HTTP)
- ViewPager打造轮播图(Banner)\引导页(Guide)
- JS实现继承
- Vue系列: 如何通过组件的属性props设置样式
- java 中Map List 等集合只能存放Integer Long
- android.content.res.Resources$NotFoundException:String resource ID #xxxx
- <戏说春秋>第三关 窃符救赵
- android之JNI开发步骤总结
- 灰度共生GLCM