Socket与SocketChannel
⽹络由下往上分为物理层、数据链路层、⽹络层、传输层、会话层、表⽰层和应⽤层。 通过初步的了解,我知道IP协议对应于⽹络
层,TCP协议对应于传输层,⽽HTTP协议对应于应⽤层,三者从本质上来说没有可⽐性,socket则是对 TCP/IP协议的封装和应⽤(程序员层⾯上)。也可以说,TPC/IP协议是传输层协议,主要解决数据如何在⽹络中传输,⽽HTTP是应⽤层协议,主要 解决如何包装数据。socket是对TCP/IP协议的封装,Socket本⾝并不是协议,⽽是⼀个调⽤接⼝(API)。 通过Socket,我们才能使⽤TCP/IP协议。
⼀、利⽤Socket建⽴⽹络连接的步骤
建⽴Socket连接⾄少需要⼀对套接字,其中⼀个运⾏于客户端,称为ClientSocket ,另⼀个运⾏于服务器端,称为ServerSocket 。套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
1、服务器监听:服务器端套接字并不定位具体的客户端套接字,⽽是处于等待连接的状态,实时监控⽹络状态,等待客户端的连接请求。
2、客户端请求:指客户端的套接字提出连接请求,要连接的⽬标是服务器端的套接字。为此,客户端的
套接字必须⾸先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端⼝号,然后就向服务器端套接字提出连接请求。
3、连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建⽴⼀个新的线程,把服务器端套接字的描述发给 客户端,⼀旦客户端确认了此描述,双⽅就正式建⽴连接。⽽服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
⼆、HTTP链接的特点
HTTP协议即超⽂本传送协议(Hypertext Transfer Protocol ),是Web联⽹的基础,也是⼿机联⽹常⽤的协议之⼀,HTTP协议是建⽴在TCP协议之上的⼀种应⽤。HTTP连接最显著的特点是客户端发送的每次请求 都需要服务器回送响应,在请求结束后,会主动释放连接。从建⽴连接到关闭连接的过程称为“⼀次连接”。
三、TCP和UDP的区别
1、TCP是⾯向链接的,虽然说⽹络的不安全不稳定特性决定了多少次握⼿都不能保证连接的可靠性,但TCP的三次握⼿在最低限度上(实际上也很⼤程度上 保证了)保证了连接的可靠性;⽽UDP不是⾯向连接的,UDP传送数据前并不与对⽅建⽴连接,对接收到的数据也不发送确认信号,发送端不知道数据是否会正 确接收,当然也不⽤重发,所以说UDP是⽆连接的、不可靠的⼀种数据传输协议。
2、也正由于1所说的特点,使得UDP的开销更⼩数据传输速率更⾼,因为不必进⾏收发数据的确认,所以UDP的实时性更好。
四、Socket、SocketChannel有什么区别
Socket、SocketChannel⼆者的实质都是⼀样的,都是为了实现客户端与服务器端的连接⽽存在的,但是在使⽤上,却有很⼤的区别。具体如下:
1.所属包不同
Socket在java包中,⽽SocketChannel在java.nio包中。
2.异步⽅式不同
从包的不同,我们⼤体可以推断出他们主要的区别:Socket是阻塞连接(当然我们可以⾃⼰实现⾮阻塞),SocketChannel可以设置⾮阻塞连接。
使⽤ServerSocket、Socket类时,服务端Socket往往要为每⼀个客户端Socket分配⼀个线程,⽽每⼀个线程都有可能处于长时间的阻塞状态中。过多的线程也会影响服务器的性能(可以使⽤线程池优化,具体看这⾥:如何编写多线程Socket程序)。⽽使⽤SocketChannel、ServerSocketChannel类可以⾮阻塞通信,这样使得服务器端只需要⼀个线程就能处理所有客户端socket的请求。
3.性能不同
⼀般来说使⽤SocketChannel会有更好的性能。其实,Socket实际应该⽐SocketChannel更⾼效,不过由于使⽤者设计等原因,效率反⽽⽐直接使⽤SocketChannel低。
4.使⽤⽅式不同
Socket、ServerSocket类可以传⼊不同参数直接实例化对象并绑定ip和端⼝,如:
Socket socket = new Socket("127.0.0.1", "8000");
ServerSocket serverSocket = new ServerSocket("8000");
⽽SocketChannel、ServerSocketChannel类需要借助Selector类控制,如:
private SocketChannel mSocketChannel;
private Selector mSelector;
private static boolean sIsGoOn = true;
private static final int MAX_BUFFER_SPACE = 2048;
实例化类和实例化对象/**
* 建⽴ Socket 连接
* @param host 服务器 ip
* @param port 服务器端⼝号
* @return 返回建⽴ socket 连接的结果i
*/
public boolean open(String host, String port) {
if (TextUtils.isEmpty(host) || TextUtils.isEmpty(port)) {
LogUtil.e( "host or port error.");
return false;
}
try {
mSelector = Selector.open();
mSocketChannel = SocketChannel
.open(new InetSocketAddress(host, Integer.parseInt(port)));
e.printStackTrace();
return false;
}
return true;
}
/**
* 发送报⽂
* @param sendPacket 待发送的报⽂
* @return 返回发送结果
*/
public int sendPacket(byte[] sendPacket) {
int count = 0;
try {
sIsGoOn = true;
while (sIsGoOn && mSelector.select() > 0) {
Iterator iterator = mSelector.selectedKeys().iterator();
while (sIsGoOn && iterator.hasNext()) {
SelectionKey selectionKey = (SelectionKey) ();
if (selectionKey.isWritable()) {
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
ByteBuffer byteBuffer = ByteBuffer.wrap(sendPacket, 0, sendPacket.length);
count = socketChannel.write(byteBuffer);
LogUtil.i( "Send ok.");
return count;
}
LogUtil.i( "sendPacket: ");
mSelector.selectedKeys().remove(selectionKey);
}
}
} catch (IOException e) {
e.printStackTrace();
return -1;
}
return count;
}
/**
* 接收来⾃服务器的报⽂
* @return 返回接收的报⽂
*/
public byte[] receivePacket() {
byte[] receivedPacket = null;
int count;
try {
sIsGoOn = true;
while (sIsGoOn && mSelector.select() > 0) {
Iterator iterator = mSelector.selectedKeys().iterator();
while (sIsGoOn && iterator.hasNext()) {
SelectionKey selectionKey = (SelectionKey) ();
try {
if (selectionKey.isReadable()) {
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
ByteBuffer byteBuffer = ByteBuffer.allocate(MAX_BUFFER_SPACE);
byteBuffer.clear();
count = ad(byteBuffer);
byteBuffer.flip();
if (count > 0) {
receivedPacket = new byte[count];
System.arraycopy(byteBuffer.array(), 0, receivedPacket, 0, count);
}
break;
}
} catch (CancelledKeyException e) {
selectionKey.cancel();
LogUtil.e( e.getMessage());
}
mSelector.selectedKeys().remove(selectionKey);
}
if (receivedPacket != null) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return receivedPacket;
}
/**
* 关闭 Socket 连接
*/
public void close() {
try {
if (mSocketChannel != null && mSocketChannel.isConnected()) {
mSocketChannel.finishConnect();
mSelector.close();
sIsGoOn = false;
mSocketChannel.close();
LogUtil.i( "close: ");
}
} catch (IOException e) {
e.printStackTrace();
}
}
这些操作均需要在⼦线程进⾏
private static final int RETRY_MAX_COUNT = 6;
private static final String CARD_ERROR = "cardError";
private byte[] mReceivePacket;
/**
* 建⽴ Socket 连接,⽤于发送报⽂
*/
private PacketSocket mPacketSocket;
private IPacketModelInterface mModelInterface;
/
**
* 临时使⽤
*/
private CommunicationInfo mCommunicationInfo;
* 尝试发送的次数
*/
private int mSendNum;
private BasePacket mPacket;
public PacketTransferTask(Context context, IPacketModelInterface modelInterface,
BasePacket packet) {
mPacketSocket = new PacketSocket();
mCommunicationInfo = new CommunicationInfo(context);
mPacket = packet;
mModelInterface = modelInterface;
}
@Override
protected String doInBackground(byte[]... sendPacket) {
LogUtil.i( "doInBackground: sendPacket" + ConvertUtil.bytesToHexString(sendPacket[0]));
while (ConsumeData().getCardType() == ConsumeInfoUtil.CARD_TYPE_IC && !BasePacketPresenter.sIsReverse) {
int flag = ConsumeData().getSearchCardResponse();
if (flag != 0 && flag != 1) {
return null;
}
if (ConsumeData().isCanSendPacket()) {
LogUtil.i( "generatePacket again");
mPacket.clearPacket();
sendPacket[0] = atePacket();
break;
}
}
publishProgress(SocketEvent.SOCKET_STATUS_CONNECTING);
String ip = HostIP();
String port = HostPort();
if (ip == null || port == null) {
ip = SpareHostIP();
port = SpareHostPort();
mSendNum = 3;
if (ip == null || port == null) {
LogUtil.e( "ip or port is null");
return SocketEvent.SOCKET_ERROR_IP_PORT;
}
}
while (mSendNum < RETRY_MAX_COUNT) {
if (isCancelled()) {
return null;
}
if (mSendNum == 3) {
ip = SpareHostIP();
port = SpareHostPort();
}
if (!mPacketSocket.open(ip, port)) {
LogUtil.e( mSendNum + " open failed");
mSendNum++;
} else {
LogUtil.e( mSendNum + " open success");
break;
}
}
if (mSendNum == 6) {
LogUtil.e( "socket open failed.");
return SocketEvent.SOCKET_ERROR_CONNECT;
publishProgress(SocketEvent.SOCKET_STATUS_SENDING);
if (sendPacket[0] != null && mPacketSocket.sendPacket(sendPacket[0]) <= 0) {
LogUtil.e( "send packet failed.");
return SocketEvent.SOCKET_ERROR_SEND;
}
publishProgress(SocketEvent.SOCKET_STATUS_RECEIVERING);
try {
mReceivePacket = ivePacket();
} catch (ClosedSelectorException e) {
LogUtil.e( e.getMessage());
}
if ((mReceivePacket == null) || (mReceivePacket.length <= 0)) {
LogUtil.e( "receive packet failed.");
return SocketEvent.SOCKET_ERROR_RECEIVER;
}
int isCard = ConsumeData().getCardType();
LogUtil.i( "isCard: " + isCard);
LogUtil.i( "sIsReverse: " + BasePacketPresenter.sIsReverse);
if (isCard == ConsumeInfoUtil.CARD_TYPE_IC && !BasePacketPresenter.sIsReverse) {
String domain39Data = ConvertUtil
.UnpackDomainData(39, mReceivePacket));
String domain55Data = ConvertUtil
.UnpackDomainData(55, mReceivePacket));
int result;
result = ConsumeData().getSearchCardResponse();
if (result != 1) {
}
while (true) {
if (!ReplyCodeUtil.REPLY_CODE_00.equals(domain39Data)) {
break;
}
result = ConsumeData().getSearchCardResponse();
if (result != 1 && result != 0) {
TradeDatabaseUtils.saveReverseInfo(ReplyCodeUtil.REPLY_CODE_96);
return CARD_ERROR;
} else if (result != 0) {
break;
}
if (ConsumeData().getConsumeType() == PacketTypes.PACKET_BALANCE_INQUIRY) { break;
}
}
}
return SocketEvent.SOCKET_SUCCESS;
}
@Override
protected void progress) {
mModelInterface.updatePacketSocketProgress(progress[0]);
}
@Override
protected void onPostExecute(String socketResult) {
if (isCancelled()) {
return;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论