Socket通信,PC-pc,pc-Android
来源:互联网 发布:java多线程面试 编辑:程序博客网 时间:2024/04/29 16:09
Socket通信
PC与PC,PC与Android的Socket通信
本程序已经本人虚拟机,实体机验证。Android版本在4.0以上。
本人是初学者,因为喜欢业余做游戏,涉及到socket通信,参考许多资料和网上各位大神传的程序,还是遇到许多bug,经过一点点的查找整理,调试,分析,终于通信成功。本文服务端是一对多通信,使用本人的PC机做服务端,客户端分别用:本人PC机,Android模拟器(4.4.2),以及公司用的mid(android系统的平板电脑),
需要注意的地方:服务端采用线程来处理每个客户端的通信,客户端(尤其是Android4.0以上版本)采用线程来发送接收数据与服务端通信(刚开始没有采用线程,直接搬网上一些大神的程序,他们许多是在2.3版本做的,在4.0以上版本总是出问题)。另外需要注意:控件不能在子线程中修改,按键监控,线程判断等。
下面贴出程序:
PC机主控端:
a.主程序
importjava.io.IOException;
import java.net.ServerSocket;
importjava.net.Socket;
publicclass MultiServer {
publicstaticdoublearea=0;
public MultiServer() {
//TODOAuto-generated constructor stub
}
publicstaticvoid main(String[] args) {
//TODOAuto-generated method stub
try{
System.out.println("服务器启动了");
ServerSocket serverSocket = new ServerSocket(12345);
Socket connectToClient = null;
while(true){//这是一个无限循环
//等待客户请求
connectToClient =serverSocket.accept();
//
new ServerThread(connectToClient);
}
}catch(IOException e){
e.printStackTrace();
}
}
}
b.线程处理程序:
importjava.io.DataInputStream;
importjava.io.DataOutputStream;
importjava.io.IOException;
importjava.net.Socket;
publicclass ServerThreadextends Thread {
private SocketconnectToClient;//声名套接字
private DataInputStreaminFromClient;//声名数据输入流
private DataOutputStreamoutToClient;//声名数据输出流
//private double area=0;
public ServerThread(Socket socket)throws IOException {
//TODOAuto-generated constructor stub
super();
connectToClient = socket;//实例化
inFromClient =newDataInputStream(connectToClient.getInputStream());
outToClient =new DataOutputStream(connectToClient.getOutputStream());
start();//启动run()方法
}
publicvoid run(){
String str;
double radius=0;//area=0;
boolean goon =true;
try{
System.out.println("有客户端连接到服务器了");
while(goon){
str = inFromClient.readUTF();
if(!str.equals("bye")){
if(str.equals("接受")){
str = inFromClient.readUTF();
radius = Double.parseDouble(str);
System.out.println("接收到的半径值为:" +radius);
MultiServer.area = radius*radius*Math.PI;
str = Double.toString(MultiServer.area);
System.out.println("圆面积是"+str);
outToClient.writeUTF("我已经准备好了,快来接收吧");
outToClient.flush();
System.out.println("连接服务器成功了");
}
//str = inFromClient.readUTF();
elseif(str.equals("发送")){
System.out.println("要发送的圆面积是:" +MultiServer.area);
str = Double.toString(MultiServer.area);
outToClient.writeUTF(str);
outToClient.flush();
System.out.println("圆面积"+str+"已经发送");
System.out.println("连接服务器成功了");
}
}else{
goon = false;
outToClient.writeUTF("bye");
outToClient.flush();
System.out.println("连接服务器结束了");
}
}
inFromClient.close();
outToClient.close();
connectToClient.close();
}catch(IOException e){
e.printStackTrace();
}
}
public ServerThread(Runnable target) {
super(target);
//TODOAuto-generated constructor stub
}
public ServerThread(String name) {
super(name);
//TODOAuto-generated constructor stub
}
public ServerThread(ThreadGroup group, Runnable target) {
super(group, target);
//TODOAuto-generated constructor stub
}
public ServerThread(ThreadGroup group, String name) {
super(group, name);
//TODOAuto-generated constructor stub
}
public ServerThread(Runnable target, String name) {
super(target, name);
//TODOAuto-generated constructor stub
}
public ServerThread(ThreadGroup group, Runnable target, String name) {
super(group, target, name);
//TODOAuto-generated constructor stub
}
public ServerThread(ThreadGroup group, Runnable target, String name,
long stackSize) {
super(group, target, name, stackSize);
//TODOAuto-generated constructor stub
}
}
2.pc机客户端:
importjava.io.BufferedReader;
importjava.io.DataInputStream;
importjava.io.DataOutputStream;
importjava.io.IOException;
importjava.io.InputStreamReader;
import java.net.Socket;
publicclass Client {
public Client() {
//TODOAuto-generated constructor stub
}
publicstaticvoid main(String[] args) {
//TODOAuto-generated method stub
try{
//连接到本机,端口号是5500
Socket connectToServer = new Socket("localhost",12345);
//将数据输入流连接到socket
DataInputStream inFromServer = new DataInputStream(
connectToServer.getInputStream());
//将数据输出流连接到socket
DataOutputStream outToServer = new DataOutputStream(
connectToServer.getOutputStream());
System.out.println("输入半径数值发送到服务器,输入bye结束。");
String outStr,inStr;
boolean goon =true;
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
//反复读用户数据并计算
while(goon){
outToServer.writeUTF("接受");
outToServer.flush();
outStr = buf.readLine();//读入用户输入
outToServer.writeUTF(outStr);
outToServer.flush();
inStr = inFromServer.readUTF();
System.out.println("收到的握手信号是: "+inStr);
if(inStr.equals("我已经准备好了,快来接收吧"))
{
//System.out.println("程序走到这一步了吗?");
outToServer.writeUTF("发送");
outToServer.flush();
inStr = inFromServer.readUTF();
}
if(!inStr.equals("bye")){
System.out.println("从服务器返回的结果是: "+inStr);
}else{
goon = false;
System.out.println("从服务器返回的结果结束! ");
}
}
inFromServer.close();
outToServer.close();
connectToServer.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
3.Android客户端
a.Main.xml:
<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<Button
android:id="@+id/rev"
android:text="接收显示"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/out"
android:text="获取发送"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<EditText
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="请输入半径值:"
/>
<!--android:text="请输入半径值:" -->
<EditText
android:id="@+id/display"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="请查看圆面积为"
/>
<!--android:text="圆面积为:" -->
<TextView
android:id="@+id/receiver"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="IsTransproting...."/>
<!-- <TextView
android:id="@+id/outputer"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="IsTransporting...." /> -->
</LinearLayout>
b.Mainfest
<?xmlversion="1.0"encoding="utf-8"?>
<manifestxmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rocketandclient"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19"/>
<uses-permissionandroid:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name="com.example.rocketandclient.Main"
android:label="@string/app_name">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
主要是开机网络通信:<uses-permissionandroid:name="android.permission.INTERNET"/>
C.Main.class
packagecom.example.rocketandclient;
import java.io.DataInputStream;
importjava.io.DataOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.net.InetAddress;
importjava.net.Socket;
importjava.net.UnknownHostException;
importcom.example.rocketandclient.R;
importcom.example.rocketandclient.Main.outputerlistenr;
importcom.example.rocketandclient.Main.receiverlistenr;
importandroid.app.Activity;
importandroid.app.ActionBar;
importandroid.app.Fragment;
importandroid.os.Bundle;
importandroid.os.Handler;
import android.os.Message;
importandroid.util.Log;
importandroid.view.LayoutInflater;
importandroid.view.Menu;
importandroid.view.MenuItem;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.view.View.OnClickListener;
import android.widget.Button;
importandroid.widget.EditText;
importandroid.widget.TextView;
importandroid.os.Build;
/***
*注意,以下采用两种方法实现添加线程
*@author Administrator
*
*/
publicclass Mainextends Activityimplements OnClickListener, Runnable {// //implements Runnable
private ButtonbtnRev=null;
private ButtonbtnOut=null;
private TextViewrevtext=null;
private EditTextoutText=null;
private EditTextdisplayText=null;
private Stringstr;
private DataInputStreaminRec=null;
private DataOutputStreamoutput=null;
private InetAddressserverAddr ;
private Threadth1,th2,th;
private SocketmSocket;
//public final boolean sendMessage (Message msg);
//public void handleMessage (Message msg);
@Override
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnRev=(Button)findViewById(R.id.rev);
btnOut=(Button)findViewById(R.id.out);
outText=(EditText)findViewById(R.id.show);
displayText=(EditText)findViewById(R.id.display);
revtext=(TextView)findViewById(R.id.receiver);
/*
* 注意两种按键监听的写法,一种需要执行OnClickListener接口,
* btnOut.setOnClickListener(this);
*并且重写 @Override
*public void onClick(View v)
*一种:rev.setOnClickListener(newreceiverlistenr());需要写内部类:
*class receiverlistenr implements OnClickListener{
* public void onClick(View v) { ;}}
*
*/
//rev.setOnClickListener(newreceiverlistenr());
//out.setOnClickListener(newoutputerlistenr());
btnRev.setOnClickListener(this);
btnOut.setOnClickListener(this);
/*if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}*/
}
class receiverlistenrimplements OnClickListener{
publicvoid onClick(View v) { //TODO Auto-generated method stub
Log.v(str,"接收操作");
th2 = new Thread(new SocketInRun());
th2.start();
}
}
class outputerlistenrimplementsOnClickListener{
publicvoid onClick(View v) { //TODO Auto-generated method stub
Log.v(str,"进入发送操作");
th1 = new Thread(new SocketOutRun());
th1.start();
}
}
class SocketInRunimplementsRunnable {
@Override
publicvoid run(){
try {
//实例化Socket
Socketsocket2 = null;
serverAddr = InetAddress.getByName("192.168.9.124");
socket2=new Socket("192.168.9.124",12345);
output =new DataOutputStream(socket2.getOutputStream());
output.writeUTF("发送");
output.flush();
//获得输入流
inRec=new DataInputStream(socket2.getInputStream());
String msg="";
str=msg =inRec.readUTF();
Log.v(str,"接收到的圆面积是:msg"+str);
//设置文本框的字符串
//displayText.setText(msg);
//Main.revtext.setText(msg);//子线程内不能设置控件,否则程序崩溃
Log.v(msg,"接收到的圆面积是:"+msg);
inRec.close();
socket2.close();
}
catch (UnknownHostException e) { //TODOAuto-generated catch block
e.printStackTrace();
}
catch (IOException e) { //TODOAuto-generated catch block
e.printStackTrace();
}
}
}
class SocketOutRunimplementsRunnable {
@Override
publicvoid run(){
try {
//实例化Socket
Socketsocket1 = null;
serverAddr = InetAddress.getByName("192.168.9.124");
Log.v(str,"进入发送操作1");
socket1=new Socket("192.168.9.124",12345);
Log.v(str,"进入发送操作2");
Stringmsg = outText.getText().toString();
output =new DataOutputStream(socket1.getOutputStream());
output.writeUTF("接受");
output.flush();
output.writeUTF(msg);
output.flush();
output.close();
socket1.close();
}
catch (UnknownHostException e) { //TODOAuto-generated catch block
e.printStackTrace();
}
catch (IOException e) { //TODOAuto-generated catch block
e.printStackTrace();
}
} //catch(Exceptione){}
}
@Override
publicvoid onClick(View v) {
//TODOAuto-generated method stub
if(v ==btnRev){
Log.v(str,"接收操作");
//th2 = new Thread(new SocketInRun());
th2 =new Thread(this);//线程实例化
th2.start();//线程启动
//displayText.setText(str);
//revtext.setText(str);
}
if(v ==btnOut){
Log.v(str,"进入发送操作");
//th1 = new Thread(new SocketOutRun());
th1 =new Thread(this);
th1.start();
}
}
@Override
publicvoid run() {
//TODOAuto-generated methodstubthis
th =new Thread(this);
if(th.currentThread() == th1){//判断当前执行的是哪个线程,如果是线程1,操作发送程序
Log.v(str,"1");
try {
//实例化Socket
Socket socket1 = null;
serverAddr = InetAddress.getByName("192.168.9.124");
Log.v(str,"进入发送操作1");
socket1=new Socket("192.168.9.124",12345);
Log.v(str,"进入发送操作2");
String msg = outText.getText().toString();
output =new DataOutputStream(socket1.getOutputStream());//实例化输出流
output.writeUTF("接受");//写数据
output.flush();//
output.writeUTF(msg);
output.flush();
output.close();
socket1.close();
}
catch (UnknownHostException e) { //TODOAuto-generated catch block
e.printStackTrace();
}
catch (IOException e) { //TODOAuto-generated catch block
e.printStackTrace();
}
}
if(th.currentThread() == th2){//如果是进程2则操作下面接收到数据
Log.v(str,"2");
try {
//实例化Socket
Socket socket2 = null;
String msg="";
serverAddr = InetAddress.getByName("192.168.9.124");
socket2=new Socket("192.168.9.124",12345);//设置机器所用的网络IP,要与PC机保持一致,端口自定义
output =new DataOutputStream(socket2.getOutputStream());
output.writeUTF("发送");
output.flush();
//获得输入流
inRec=new DataInputStream(socket2.getInputStream());
str=msg =inRec.readUTF();//读数据
//msg = inRec.readUTF();
Message msgg = new Message();
msgg.what = 100;
this.mHandler.sendMessage(msgg);
Log.v(msg,"接收到的圆面积是:"+msg);
inRec.close();
socket2.close();
}
catch (UnknownHostException e) { //TODOAuto-generated catch block
e.printStackTrace();
}
catch (IOException e) { //TODOAuto-generated catch block
e.printStackTrace();
}
}
}
/*
*注意控件的设置不能在子线程中操作,需要在主线程中。
*需要子线程中参数来改变控件的请注意以下方法
*
*/
privateHandlermHandler =new Handler() {
publicvoid handleMessage(Message msg) {
switch (msg.what){
case 100:
displayText.setText(str);
revtext.setText(str);
break;
}
}
};
}
- Socket通信,PC-pc,pc-Android
- Android与PC的socket通信
- android与pc的socket通信JAVA
- Android客户端与PC进行Socket通信
- Android手机通过socket与pc通信
- Android手机通过socket与pc通信
- Android与PC通信之Socket
- Android手机通过socket与pc通信
- Android手机通过socket与pc通信
- Android与PC间进行Socket通信
- Android Socket 访问PC
- Android和PC通信
- pc
- android实现PC到手机的SOCKET通信
- android使用socket于本地PC进行通信的问题
- PC客户端与Android服务端的Socket同步通信
- Android 手机端与pc服务器之Socket通信
- android虚拟机和Pc或二个虚拟机Socket通信
- POJ 3074 Sudoku(数据结构,DLX)
- Ubuntu下载android 源码
- PKU 2774 Long Long Message (后缀数组练习模板题)
- 正则表达式的几个用途
- 第三方登录
- Socket通信,PC-pc,pc-Android
- NSPredicate的使用
- 请不要做浮躁的人
- Objective-C 是如何慢慢走红的?
- 户外广告作用
- Netty In Action 读书笔记 - 第五章 Buffer
- HDFS体系结构
- com.microsoft.sqlserver.jdbc.SQLServerException: 必须声明标量变量 "@P8sImage_big2"。
- Struts2_三种传参数方法