Windows的C++服务器和Android客户端用Socket通信,为什么会报IOException?

暗黑Zero 2015-03-04 12:40:30
Android中的接收线程是这样的:
	class GetThread implements Runnable
{
@Override
public void run()
{
try
{
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true)
{
String input = in.readLine();
if(input!=null)
{
Message msg = new Message();
msg.obj = input;
handler.sendMessage(msg);
}
}
}
catch (IOException e)
{
System.out.println("NetThreadIOException");
Message msg = new Message();
msg.obj = "net error";
handler.sendMessage(msg);
}


Windows上的服务器我用了一份开源的库,主程序是这样的:
#include "Socket.h"
#include<iostream>
using namespace std;

const int PORT = 12121;
const int MAX_CONNECT = 100;

int main()
{
cout<<"Working..."<<endl;
SocketServer socket(PORT, MAX_CONNECT);
cout<<"Waiting for Client"<<endl;
socket.Accept();
socket.SendLine("Hello!");
cout<<"Hello!"<<endl;
system("pause");
return 0;
}


其中SendLine函数是这么写的:
void Socket::SendLine(std::string s) {
s += '/n';
send(s_,s.c_str(),s.length(),0);
}


现在现象是:打开服务器后,运行客户端,客户端能够正确连接至服务器,但是服务器发给他“Hello”时,客户端接收不到,并报IOException。

这份代码之前我曾在多个地方用过,只不过当时的服务器不同,一个是用Java写的,一个是用Linux的C++写的……

想知道出错的可能原因? 谢谢~~
...全文
231 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_33455714 2015-12-21
  • 打赏
  • 举报
回复
请问join()等待写在哪里 我也遇到了同样的问题
暗黑Zero 2015-03-04
  • 打赏
  • 举报
回复
引用 2 楼 dalor 的回复:
client_socket_manager.login();这句开的线程在login,马上就执行下一句 client_socket_manager.openGetThread(); 如果login的线程挂起或未login成功,那socket肯定是null,后面读信息,怎么读呢? 应该是确保login成功后,再oopenGetThread()。
谢谢,检查了一下,确实是这个的问题,我现在用join()等待LoginThread结束以后再执行openGetThread就没问题了~
开发者_android 2015-03-04
  • 打赏
  • 举报
回复
client_socket_manager.login();这句开的线程在login,马上就执行下一句 client_socket_manager.openGetThread(); 如果login的线程挂起或未login成功,那socket肯定是null,后面读信息,怎么读呢? 应该是确保login成功后,再oopenGetThread()。
暗黑Zero 2015-03-04
  • 打赏
  • 举报
回复
我试着修改了一下,发现如果把接收线程写在主Activity里面,程序就是正常工作的,这说明服务器那边没有问题:
public class MainActivity extends Activity 
{
	EditText ip_box;
	Button login_button;
	TextView text;
	Handler handler;
	final int port = 12121;
	ClientSocketManager client_socket_manager;
	Socket socket;
	String ip;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		init();
		
		handler = new Handler()
		{
			public void handleMessage(Message msg)
			{
				String words = (String)msg.obj;
				if( words.equals("ok") == true )
				{
					Toast.makeText(MainActivity.this, "来自服务器的问候:登陆成功!!欢迎使用~",Toast.LENGTH_LONG).show();
					finish();
				}
				else if(words.equals("did not login") )
				{
					Toast.makeText(MainActivity.this,"ip错了或者是主机没有开", Toast.LENGTH_SHORT).show();
				}
				else
				{
					text.setText((String)msg.obj);
				}
			}
		};
		
		class GetThread implements Runnable //接收线程
		{
			public void getMsg()
			{
				try 
				{
					Scanner in = new Scanner(socket.getInputStream());
					String gotmsg = in.nextLine();
					Message msg = new Message();
					msg.obj = gotmsg;
					MainActivity.this.handler.sendMessage(msg);
					
				} catch (UnknownHostException e) 
				{
					Message msg = new Message();
					msg.obj = "net error";
					MainActivity.this.handler.sendMessage(msg);
				} catch (IOException e) 
				{
					Message msg = new Message();
					msg.obj = "net error";
					MainActivity.this.handler.sendMessage(msg);
				}
				
			}
			
			@Override
			public void run() 
			{
				try 
				{
					socket = new Socket();
					socket.connect(new InetSocketAddress(ip, port) , 5000);
				} catch (UnknownHostException e) 
				{
					Message msg = new Message();
					msg.obj = "did not login";
					MainActivity.this.handler.sendMessage(msg);
				} catch (IOException e) {
					Message msg = new Message();
					msg.obj = "did not login";
					MainActivity.this.handler.sendMessage(msg);
				}
				
				if( socket != null)
					getMsg();
				else
				{
					Message msg = new Message();
					msg.obj = "did not login";
					MainActivity.this.handler.sendMessage(msg);
				}
			}
		}
		
		login_button.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View arg0) 
			{
				// TODO Auto-generated method stub
				ip = ip_box.getText().toString();
				client_socket_manager = new ClientSocketManager(ip, port, handler);
				boolean logged = client_socket_manager.login();
				GetThread g = new GetThread();
				new Thread(g).start();
			}
			
		});
	}

}
但是,我试图把网络操作分离出去的时候,就会出现IOException,分离之后的代码如下:
public class ClientSocketManager //管理网络的类
{
	String ip;
	int port;
	Socket socket;
	Handler handler; //通过这个handler发消息
	
	/**
	 * Thread to get message from server
	 * @author Zero
	 *
	 */
	class GetThread implements Runnable
	{
		@Override
		public void run() 
		{
			try 
			{
				BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				while(true)
				{
					String input = in.readLine();
					if(input!=null)
					{
						Message msg = new Message();
						msg.obj = input;
						handler.sendMessage(msg);
					}
				} 
			}
			catch (IOException e) 
			{
				System.out.println("NetThreadIOException");
				Message msg = new Message();
				msg.obj = "net error";
				handler.sendMessage(msg);
			}
			catch (NullPointerException e)
			{
				//System.out.println("NetThreadIOException");
				Message msg = new Message();
				msg.obj = "net error";
				handler.sendMessage(msg);
			}
		}
	}
	
	/**
	 * Thread to login to server
	 * @author Zero
	 *
	 */
	class LoginThread implements Runnable
	{
		boolean ok;
		@Override
		public void run() 
		{
			try 
			{
				socket = new Socket();
				socket.connect(new InetSocketAddress(ip, port) , 5000);
			} catch (UnknownHostException e) 
			{
				System.out.println("UnknownHostException");
				Message msg = new Message();
				msg.obj = "did not login";
				handler.sendMessage(msg);
				ok=false;
			} catch (IOException e) {
				System.out.println("IOException");
				Message msg = new Message();
				msg.obj = "did not login";
				handler.sendMessage(msg);
				ok=false;
			}
		}
	}
	
	public ClientSocketManager(){}
	
	/**
	 * Create a new ClientSocketManager
	 * @param _ip
	 * @param _port
	 * @param _handler
	 */
	public ClientSocketManager(String _ip, int _port, Handler _handler)
	{
		ip = _ip;
		port = _port;
		handler = _handler;
	}
	
	public boolean login()
	{
		LoginThread login_thread = new LoginThread();
		new Thread(login_thread).start();

		return login_thread.ok;
		
	}
	
	public void openGetThread()
	{
		GetThread getThread = new GetThread();
		new Thread(getThread).start();
	}
}

然后主Activity中:
login_button.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View arg0) 
			{
				// TODO Auto-generated method stub
				ip = ip_box.getText().toString();
				client_socket_manager = new ClientSocketManager(ip, port, handler);
				boolean logged = client_socket_manager.login();
				//if(!logged)
				//	return;
				client_socket_manager.openGetThread();
			}
			
		});
这样就会在input = in.readLine()那一行爆出IOException。请问这是怎么回事?谢谢~~
源码直接下载地址: https://pan.quark.cn/s/8ac6a8c064f8 Intellij Idea 12 外部jar包导入操作指南 Intellij Idea 12作为一款功能丰富且被广泛采纳的集成开发环境(IDE),为开发者提供了多种便利的工具以支持快速且高效的软件开发与调试工作。在众多功能中,从外部导入jar包是Intellij Idea 12的一项核心操作,接下来的内容将系统性地阐释如何在Intellij Idea 12环境中执行外部jar包的导入操作。 _步骤一:进入项目结构设置界面_ 启动Intellij Idea 12软件,加载一个既有的项目或新建一个项目,随后通过点击“文件”(File)菜单并从下拉选项中选择“项目结构”(Project Structure),此操作将引导用户进入项目结构配置界面。 _步骤二:执行模块添加流程_ 在呈现的项目结构配置界面中,用户需选择“模块”(Modules)这一选项卡,随后点击界面上的“+”符号,并从弹出的列表中选择“JARs or directories”(jar文件或目录),这一步骤将触发“添加jar或目录”(Add Jar or Directory)的对话框显示。 _步骤三:指定要导入的jar文件_ 在“添加jar或目录”(Add Jar or Directory)的对话框中,用户需要浏览并选中计划导入的jar文件,之后点击“确定”(OK)按钮,以完成jar文件的添加过程至项目中。 _步骤四:验证jar文件的导入状态_ 完成上述步骤后,用户可返回至项目结构配置界面,并在“依赖项”(Dependencies)选项卡下查看到新添加的jar文件,这证明了jar文件已成功被导入至项目中。 _注意事项_...

80,488

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧