androidsocks
㈠ android如何与手机进行通信(Socket连接)
其实跟电脑差不多了,android里调用socket的方法,拿到socket后就可以发送数据并接收数据。
我最近正在做android方面的通信,真的想把完整的代码都给你,可是没办法,公司机密。。
给你我的socket连接类吧。。。
package sean.socket;
///////////把MyType的一些方法替换成Writer的方法
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import sean.Sysout;
import sean.business.BusinessCenter;
import sean.business.LoginManager;
import sean.format.MyType;
import sean.io.Reader;
import sean.transfer.BytesBuffer;
import sean.transfer.DataCenter;
public class SocketThread implements Runnable {
String Server = "";
int Port = 0;
static Socket cs = null;
// Thread ioThread=null;
static boolean bool_SocketThread = false;
static OutputStream output = null;
public SocketThread(String server, int port) {
Server = server;
Port = port;
bool_SocketThread = true;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (bool_SocketThread) {
try {
// if (cs == null) {
DataCenter.setBool_Login(false);// 设置登录失败
Sysout.println("正在尝试连接ClientSocket...", Sysout.TempOutDebug);
cs = new Socket(InetAddress.getByName(Server), Port);
if (cs != null) {
Sysout.println("ClientSocket连接成功!__" + cs,
Sysout.TempOutDebug);
cs.setKeepAlive(true);//让socket保持活动状态
InputStream input = cs.getInputStream();
output = cs.getOutputStream();
BusinessCenter.sendLoginData();
BytesBuffer bBuffer = new BytesBuffer();
byte[] Buffer = new byte[1024];
int ReadBytes = input.read(Buffer);
while (ReadBytes != -1) {
Sysout.println("已读取" + ReadBytes + "个字节到缓冲区",
Sysout.TempOutDebug);
byte[] b = new byte[ReadBytes];
b = MyType.BytesInsertToBytes(Buffer, b, 0);
Reader r = new Reader(b);
Sysout.println(r.toString() + "____ReadBytes=="
+ ReadBytes, Sysout.TempOutDebug);
bBuffer.InsertToBuffer(Buffer, ReadBytes);
ReadBytes = input.read(Buffer);
}
} else {
Sysout.printException("ClientSocket连接失败!请确认网络正常且服务器已开启。");
}
// }
// 执行到这里说明inputstream.read()已中断,说明socket已断开连接
// cs=null;
LoginManager.setLoginValue(-1);// 业务中心登录注销,即登录管理器注销登录
DataCenter.setBool_Login(false);// 数据中心登录注销
Sysout.printException(cs + "已断开。");
Thread.sleep(2 * 1000);// 睡眠2秒后继续循环
// try {
// // 判断ClientSocket是否已断开
// cs.sendUrgentData(0);
// } catch (IOException e) {
// // TODO Auto-generated catch block
// Sysout.printException("ClientSocket已断开,重新连接。"+e);
// cs.close();
// cs = null;
// }
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
Sysout.printException("SocketThread.java====解析服务器名称发生异常!" + e);
// e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
Sysout.printException("SocketThread发生IO异常,异常消息:" + e);
try {
if (cs != null) {
Sysout.println("准备关闭" + cs, Sysout.TempOutDebug);
cs.shutdownOutput();
cs.shutdownInput();
cs.close();
cs = null;
output = null;
LoginManager.setLoginValue(-1);// 业务中心登录注销,即登录管理器注销登录
DataCenter.setBool_Login(false);// 数据中心登录注销
Sysout.println(cs + "已关闭。", Sysout.TempOutDebug);
}
try {
Thread.sleep(5000);
} catch (InterruptedException e2) {
// TODO Auto-generated catch block
Sysout.printException("SocketThread.java====线程睡眠异常!!"
+ e2);
// e2.printStackTrace();
}
String ExceptionInfos=e.toString();
if(ExceptionInfos.endsWith("Connection refused")){
stopSocketThread();
}
} catch (IOException e1) {
// TODO Auto-generated catch block
Sysout.printException(cs + "关闭发生异常::" + e1);
// e1.printStackTrace();
try {
Thread.sleep(5000);
} catch (InterruptedException e2) {
// TODO Auto-generated catch block
Sysout.printException("SocketThread.java====线程睡眠异常!!"
+ e2);
// e2.printStackTrace();
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}// while(bool_SocketThread)
Sysout.println("SocketThread已停止。", Sysout.TempOutDebug);
}
public static Socket getSocket() {
return cs;
}
// public void setBool(boolean bool0) {
// bool_SocketThread = bool0;
// }
public static OutputStream getOutputStream() {
return output;
}
public static void stopSocketThread() {
try {
// 停止SocketThread线程,必须先把循环的标志bool_SocketThread置为false,否则可能继续循环,重新建立socket连接
bool_SocketThread = false;
// 关闭socket
if (cs != null) {
cs.shutdownOutput();
cs.shutdownInput();
cs.close();
cs = null;
output = null;
Sysout.println("ClientSocket已被强制关闭。");
// LoginManager.setLoginValue(-1);// 业务中心登录注销,即登录管理器注销登录
// DataCenter.setBool_Login(false);// 数据中心登录注销
// byte[] lock=LoginActivity.getLock();
// synchronized(lock){
// lock.notify();
// }
}
} catch (IOException e) {
// TODO Auto-generated catch block
Sysout.printException("强制关闭" + cs + "发生异常::" + e);
// e.printStackTrace();
}
}
}
必须先在android里启动一个服务,由服务去启动这个socket线程,因为如果是UI去启动的话,页面会卡住。。。
㈡ android socket接收事件为什么没有监听事件,要用死循环呢
socket是Java API(编程文档接口),为了直接使用Socekt服务,谷歌直接把Java的Socket模块照搬过来的
Android 的 onClikcListener onTouchEvent 等是Android API(编程文档接口)
2.设计目的
编程接口全都是根据需求设定的,比如Google事先考虑开发者有使用监听事件的需求,才预定义了onClickListener onItemListener这些接口,并且将这些底层实现,封装到了c和C++层,开发者只需要直接使用Google事先为我们准备好的接口即可。
Socket ,首先Socket并不是Google事先设计好的,Socke中文名称作套接字,你网络搜套接字编程,可以认识到Socket开发是专门的编程技术,而Socket本身又是网络通信协议的基础设施,Socket的诞生历史,高于Android,甚至高于Java,Socekt是计算机提供进程通信能力的编程接口,确切的说,它甚至可以提供不同主机间不同进程的通信能力,(包括同一主机里不同进程的通信能力)
主机?端系统?网络协议?运输层?传输层?套接字?端口?
我说的这些专业名词,也许你一时半会并不能理解
值得庆幸的是,当你了解到这里,你起码能想明白,为什么有的人说,Android 程序,也可以做服务器了,因为Socket 提供了其他端系统访问Android程序的能力,能被请求访问的程序,可以称作服务端。
想深入了解Socket的设计原理、设计本意,需要深厚的计算机网络知识,在这里我建议你阅读《计算机网络-自顶向下方法》阅读前三章,也许你对网络编程会有更深的理解。
总结来说:
Android的Listener系列监听事件,其实只是响应用户I/O操作而已,是人与硬件设备的通信,安卓系统提供维持监听事件的能力,所以你能根据某些事件作出响应
Socket的功能,是提供进程通信的能力,安卓系统并不能直接控制Socket的生命周期,它第一层设计是Java代码,并不是Google自己研发的,第二层、第三层已经直接深入到运输层协议、计算机系统层原理了,Google为了省事,直接照搬Java API ,无可厚非。
㈢ Android socket通信协议的封装和解析
android socket通信协议的封装和解析,其实是和java一样的,都是通过http中的相关知识来封装和解析,主要是通过多次握手,如下代码:
importjava.io.BufferedReader;
importjava.io.BufferedWriter;
importjava.io.IOException;
importjava.io.InputStreamReader;
importjava.io.OutputStreamWriter;
importjava.io.PrintWriter;
importjava.net.ServerSocket;
importjava.net.Socket;
importjava.util.ArrayList;
importjava.util.List;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
publicclassMain{
privatestaticfinalintPORT=9999;
privateList<Socket>mList=newArrayList<Socket>();
privateServerSocketserver=null;
=null;//threadpool
publicstaticvoidmain(String[]args){
newMain();
}
publicMain(){
try{
server=newServerSocket(PORT);
mExecutorService=Executors.newCachedThreadPool();//createathreadpool
System.out.println("服务器已启动...");
Socketclient=null;
while(true){
client=server.accept();
//把客户端放入客户端集合中
mList.add(client);
mExecutorService.execute(newService(client));//
}
}catch(Exceptione){
e.printStackTrace();
}
}
{
privateSocketsocket;
privateBufferedReaderin=null;
privateStringmsg="";
publicService(Socketsocket){
this.socket=socket;
try{
in=newBufferedReader(newInputStreamReader(socket.getInputStream()));
//客户端只要一连到服务器,便向客户端发送下面的信息。
msg="服务器地址:"+this.socket.getInetAddress()+"cometoal:"
+mList.size()+"(服务器发送)";
this.sendmsg();
}catch(IOExceptione){
e.printStackTrace();
}
}
@Override
publicvoidrun(){
try{
while(true){
if((msg=in.readLine())!=null){
//当客户端发送的信息为:exit时,关闭连接
if(msg.equals("exit")){
System.out.println("ssssssss");
mList.remove(socket);
in.close();
msg="user:"+socket.getInetAddress()
+"exittotal:"+mList.size();
socket.close();
this.sendmsg();
break;
//接收客户端发过来的信息msg,然后发送给客户端。
}else{
msg=socket.getInetAddress()+":"+msg+"(服务器发送)";
this.sendmsg();
}
}
}
}catch(Exceptione){
e.printStackTrace();
}
}
/**
*循环遍历客户端集合,给每个客户端都发送信息。
*/
publicvoidsendmsg(){
System.out.println(msg);
intnum=mList.size();
for(intindex=0;index<num;index++){
SocketmSocket=mList.get(index);
PrintWriterpout=null;
try{
pout=newPrintWriter(newBufferedWriter(
newOutputStreamWriter(mSocket.getOutputStream())),true);
pout.println(msg);
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
}
㈣ android socket怎样实现断网重连
由于当网络出现故障时,recv要很长时间才能返回,如果你觉得这种方式不能接受,可以考虑select或者其他模型。
UINT CMonitorDlg::ThreadFunction(LPVOID pParam)
{
WSADATA wsaData;
WSAStartup(...);
while(1)
{
if (WaitSingleObject(hEventKill, 0) == WAIT_OBJECT_0) //
这个hEventKill到主线程里创建,用于控制线程退出
{
break;
}
SOCKET s; //创建套接字
int port=PORT;
int iLen; //从服务器接收的数据长度
TCHAR recvbuf[BufferLen]; //接受数据的缓冲器
struct sockaddr_in serv1; //服务器端地址
serv1.sin_family=AF_INET;
//需要连接的服务器地址信息
serv1.sin_port=htons(port); //需要连接的服务器地址信息
serv1.sin_addr.s_addr=inet_addr(p->Ip); //将命令行的IP地址转化为二进制表示的网络字节顺序IP地址
s=socket(AF_INET,SOCK_STREAM,0);
if(s==INVALID_SOCKET)
{
AfxMessageBox("socket()failed");//套接字失败
return 0;
}
if(connect(s,(struct
sockaddr*)&serv1,sizeof(serv1))==INVALID_SOCKET)
{
int
b=WSAGetLastError();
//连接失败
}
else
{ //连接成功
p->connectstate=true;
do{
在此循环体中我接收数据并对数据做处理(省略部分代码)
iLen=recv(s,recvbuf,sizeof(recvbuf),0); //接收套接字中的数据放入recvbuf1缓冲区
if(iLen==0) // server调用了close
{
strtempMsg.Format(_T("局 %s 数据传送结束"),p->Name);
break;
//return 0;
}
else
if(iLen==SOCKET_ERROR) // 网络错误
{
int
err=WSAGetLastError();
if (err==WSAECONNRESET
||err==WSAECONNABORTED)
strtempMsg.Format(_T("%s连接中断"),p->Name);
p->connectstate=false;
break; //
退出do-while循环准备重连
// return -2; //连接异常中断
}
......
.....省略代码
}while//do-while
} //else
closesocket(s); //关闭套接字
} // end of
while(1)
WSACleanup();
return 0;
}
㈤ android socket有几种方法
/***第一种:客户端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();
}
㈥ android的socket怎样判断断线
非阻塞模式,如果暂时没有数据,返回的值也会是<=0的,如果用阻塞模式的话,返回<=0的值是可以认为socket已经无效了。
当使用 select()函数测试一个socket是否可读时,如果select()函数返回值为1,
且使用recv()函数读取的数据长度为0 时,就说明该socket已经断开。
经过代码试验,如果进程受到一些信号时,例如:EINTR,recv()返回值小于等于0时,这是就需要判断 errno是否等于 EINTR , 如果errno == EINTR 则说明recv函数是由于程序接收到信号后返回的,socket连接还是正常的,不应close掉socket连接。
如果write,我觉得还有一些情况需要考虑,那就是写的太快的时候,有可能buffer写满了,这是,errno是EAGAIN,可以根据实际需要,如果errno是EAGAIN的话,再写几次。
当然,read的时候也有类似write的情况,需要check一下errno,如果是EAGAIN或者EINTR,最好不要立刻终止操作,再尝试一下!
这是我写的一个代码!int SocketConnected(int sock)
{
int res,recvlen;
char buf[20] = {'\0'};
struct timeval timeout={3,0};
fd_set rdfs;
FD_ZERO(&rdfs);
FD_SET(sock,&rdfs);
res = select(sock+1,&rdfs,NULL,NULL,&timeout);
if(res > 0){
recvlen = recv(sock,buf,sizeof(buf),0);
if(recvlen > 0){
printf("socket connected\n");
return 1;
} else if (recvlen < 0 ){
if(errno == EINTR){
printf("socket connected\n");
return 1;
}else {
printf("socket disconnected! connect again!\n");
return 0;
}
} else if (recvlen == 0){
printf("socket disconnected!connect again\n");
return 0;
}
} else if(res == 0 ){
//time out
printf("socket connected\n");
return 1;
} else if(res < 0){
if (errno == EINTR){
printf("socket connected\n");
return 1;
}else{
printf("socket disconnected ! connect again!\n");
return 0;
}
}
return 0;
}