网络通信基本有Socket和HTTP协议两种,其中Socket可以用TCP或UDP;而HTTP可以用HTTP GET或POST请求,HTTP Webservice的SOAP等方式。这里重点介绍Socket,Socket代表网络套接字,用于描述IP地址和端口,即网络通信过程中端点的抽象表示。Socket类是java中运行客户端网络编程的核心类,其可以使客户端通过TCP(使用Socket类)或UDP(使用DatagramSocket类,暂不介绍)协议连接到服务器,并和服务器端进行数据交互。Socket可以进行基本的发送接收数据,还可以通过一系列的get、set方法对通讯进行调节。
Socket客户端介绍,详见如下代码:
try {
/***第一种:客户端Socket通过构造方法连接服务器***/
//客户端Socket可以通过指定IP地址或域名两种方式来连接服务器端,实际最终都是通过IP地址来连接服务器
//新建一个Socket,指定其IP地址及端口号
Socket socket = new Socket("192.168.0.7",80);
/***Socket 客户端 一些常用设置***/
//客户端socket在接收数据时,有两种超时:1.连接服务器超时,即连接超时;2.连接服务器成功后,接收服务器数据超时,即接收超时
//*设置socket 读取数据流的超时时间
socket.setSoTimeout(5000);
//发送数据包,默认为false,即客户端发送数据采用Nagle算法;
//但是对于实时交互性高的程序,建议其改为true,即关闭Nagle算法,客户端每发送一次数据,无论数据包大小都会将这些数据发送出去
socket.setTcpNoDelay(true);
//设置客户端socket关闭时,close()方法起作用时延迟1分钟关闭,如果1分钟内尽量将未发送的数据包发送出去
socket.setSoLinger(true, 60);
//设置输出流的发送缓冲区大小,默认是8KB,即8096字节
socket.setSendBufferSize(8096);
//设置输入流的接收缓冲区大小,默认是8KB,即8096字节
socket.setReceiveBufferSize(8096);
//作用:每隔一段时间检查服务器是否处于活动状态,如果服务器端长时间没响应,自动关闭客户端socket
//防止服务器端无效时,客户端长时间处于连接状态
socket.setKeepAlive(true);
/*** Socket客户端向服务器端发送数据 ****/
//客户端向服务器端发送数据,获取客户端向服务器端输出流
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
//代表可以立即向服务器端发送单字节数据
socket.setOOBInline(true);
//数据不经过输出缓冲区,立即发送
socket.sendUrgentData(65);//"A"
//向服务器端写数据,写入一个缓冲区
//注:此处字符串最后必须包含“\r\n\r\n”,告诉服务器HTTP头已经结束,可以处理数据,否则会造成下面的读取数据出现阻塞
//在write()方法中可以定义规则,与后台匹配来识别相应的功能,例如登录Login()方法,可以写为write("Login|test,123 \r\n\r\n"),供后台识别;
bw.write("Login|test,123 \r\n\r\n");
//发送缓冲区中数据,必须有
bw.flush();
/*** Socket客户端读取服务器端响应数据 ****/
//socket.isConnected代表是否连接成功过
if((socket.isConnected() == true) && (socket.isClosed() == false)){//判断Socket是否处于连接状态
//客户端接收服务器端的响应,读取服务器端向客户端的输入流
InputStream is = socket.getInputStream();
//缓冲区
byte[] buffer = new byte[is.available()];
//读取缓冲区
is.read(buffer);
//转换为字符串
String responseInfo = new String(buffer);
//日志中输出
Log.i("TEST", responseInfo);
} //关闭网络
socket.close();
/***第二种:通过connect方法连接服务器***/
Socket socket_other = new Socket();
//使用默认的连接超时
socket_other.connect(new InetSocketAddress("192.168.0.7",80));
//连接超时2s
socket_other.connect(new InetSocketAddress("192.168.0.7",80),2000);
//关闭socket
socket_other.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
/解析服务器地址和端口号
int dotPos = ipAddr.indexOf(':');
String ip = ipAddr.substring(0, dotPos).trim();
int port = Integer.parseInt(ipAddr.substring(dotPos+1).trim());
InetSocketAddress endpoint = new InetSocketAddress(ip , port);
Socket socket = null;
OutputStream out = null;
InputStream in = null;
try {
socket = new Socket();
//设置发送逗留时间2秒 //中断后未传输数据可传输的时间(秒),defalut false
socket.setSoLinger(true, 2);
//设置InputStream上调用 read()阻塞超时时间2秒
socket.setSoTimeout(2000);
//对于Socket和SeverSocket如果需要指定缓冲区大小,必须在连接之前完成缓冲区的设定。
//设置socket发包缓冲为32k;
socket.setSendBufferSize(32*1024);
//设置socket底层接收缓冲为32k
socket.setReceiveBufferSize(32*1024);
//关闭Nagle算法.立即发包
socket.setTcpNoDelay(true);
//连接服务器
socket.connect(endpoint);
//获取输出输入流
out = socket.getOutputStream();
in = socket.getInputStream();
//输出请求
out.write(datas);
out.flush();
//接收应答
BufferedReader br = new BufferedReader( new InputStreamReader(in) ,
4096);
StringWriter received = new StringWriter(4096);
char[] charBuf = new char[4096];
int size =0;
char lastChar = 0;
do {
System.out.println(charBuf);
size = br.read(charBuf , 0 , 4096);
System.out.println(size);
lastChar = charBuf[size-1];
if(lastChar == 0){
received.write(charBuf, 0, size - 1);
}
//System.out.println(received.toString());
}while(lastChar != 0);
return received.toString();
} finally {
if (out != null) {
try {
out.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
if (in != null) {
try {
in.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
在创建Socket后,系统会为新创建的套接字分配缓冲区空间。这时套接字已经具有了输入缓冲区和输出缓冲区。 缓冲区大小需要根据具体情况进行设置,一般要低于64K(TCP能够指定的最大负重载数据量,TCP的窗口大小是由16bit来确定的),增大缓冲区可以增大网络I/O的性能,而减少缓冲区有助于减少传入数据的backlog(就是缓冲长度,因此提高响应速度)。
对于Socket和SeverSocket如果需要指定缓冲区大小,必须在连接之前完成缓冲区的设定。
对于缓冲区空间的设定,要根据具体情况来定,如果存在大量的长信息(比如文件传输),将缓冲区定义的大些,可能更好的利用网络资源,如果更多的是短信息(比如聊天消息),使用小的缓冲区可能更好些,这样刷新的速度会更快。一般系统默认的缓冲大小是8*1024。除非对自己处理的情况很清晰,否则请不要随意更改这个设置。