在这里,原理就不讲了,只提供可以运行的代码,以及改如何去在软件上使用它们。
如果实在想要源码:可以点击这边:这里
https://download.csdn.net/download/qq_35594560/10306583
服务器端:
1.需要Eclipse。(自行安装)
2.创建两个类(命名为socketserver以及receive,其中socketserver是为了发送信息的,receive为了接收信息,且是一个线程)
3.socketserver代码如下:
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class socketserver {
public static void main(String[] args) throws Exception{
ServerSocket server = new ServerSocket(30003);//在端口9996开一个服务,监听客户端发来的请求,准备接收客户端发来的请求数据
Socket socket =server.accept();//只有当有客户端请求并连接时,才回返回一个Socket对象,这个对象就是带着客户端请求的那个Socket对象
System.out.println("server connected!");
//创建一个PrintWriter的实例对象out来完成服务端向客户端的输出数据的任务,
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
//单独开一个线程接收从客户端过来的请求,在Receive1类中完成数据的接收
Thread t = new Thread(new Receive1(socket));
t.start();
/*一定要理解Socket是一个用于机器之间通信的类*/
//发送数据给客户端
Scanner scanner = new Scanner(System.in);//键盘输入服务端要发给客户端的数据
while(scanner.hasNextLine()){
String data=scanner.nextLine();
out.println(data);//将键盘输入的服务端要发给客户端的数据封装在PrintWriter类的对象中
System.out.println("Server:"+data);
}
}
}
4.receive代码:
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
public class Receive1 implements Runnable {
private Socket socket;
public Receive1(Socket socket) {
this.socket=socket;//在服务端接收客户端发来的数据需要调用Receive1()这个方法,就会得到一个Socket对象,这个对象就是携带着客户端请求的socket
}
@Override
public void run() {
try {
Scanner scanner=new Scanner(socket.getInputStream());//获得客户端从键盘接收的输入流
String str = null;
while(true){
str=scanner.nextLine();
System.out.println("Client:"+str);
}
} catch (IOException e) {
e.printStackTrace();
}//接收数据
}
}
客户端:
1.需要android studio。
2.需要MainActivity以及一个类clintclass
3.MainActivity代码如下:
package com.example.wuweipeng.exp2; import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.text.method.ScrollingMovementMethod; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private EditText etMain; private Button btnMain; private TextView tvMain; private ClientThread mClientThread; //在主线程中定义Handler传入子线程用于更新TextView private Handler mHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etMain = (EditText) findViewById(R.id.et_main); btnMain = (Button) findViewById(R.id.btn_main); tvMain = (TextView) findViewById(R.id.tv_main); tvMain.setTextColor(Color.WHITE); tvMain.setMovementMethod(new ScrollingMovementMethod()); mHandler=new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 0) { tvMain.append("\n"+"Server:"+ msg.obj.toString()); } } }; //点击button时,获取EditText中string并且调用子线程的Handler发送到服务器 btnMain.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { Message msg = new Message(); msg.what = 1; msg.obj = etMain.getText().toString(); tvMain.append("\n"+"Client:"+ msg.obj.toString()); mClientThread.revHandler.sendMessage(msg); etMain.setText(""); } catch (Exception e) { e.printStackTrace(); } } }); mClientThread = new ClientThread(mHandler); new Thread(mClientThread).start(); tvMain.append("\n"+"已加入群聊"); } }
4.ClientThread代码:
package com.example.wuweipeng.exp2; /** * Created by wuweipeng on 2018/3/24. */ import android.graphics.Color; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.util.Log; import android.widget.TextView; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; /** * 项目名称:SocketTestTwo * 创建人:Double2号 * 创建时间:2016.11.20 9:16 * 修改备注: */ public class ClientThread implements Runnable { private Socket mSocket; private BufferedReader mBufferedReader = null; private OutputStream mOutputStream = null; private Handler mHandler; public Handler revHandler; public ClientThread(Handler handler) { mHandler = handler; } @Override public void run() { try { mSocket = new Socket("117.25.242.9", 30003); Log.d("MainActivity","connect success"); mBufferedReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream())); mOutputStream = mSocket.getOutputStream(); new Thread(){ @Override public void run() { super.run(); try { String content = null; while ((content = mBufferedReader.readLine()) != null) { Log.d("MainActivity",content); Message msg = new Message(); msg.what = 0; msg.obj = content; Log.d("MainActivity",msg.toString()); mHandler.sendMessage(msg); } }catch (IOException e){ e.printStackTrace(); } } }.start(); //由于子线程中没有默认初始化Looper,要在子线程中创建Handler,需要自己写 Looper.prepare(); revHandler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 1) { try { mOutputStream.write((msg.obj.toString() + "\r\n").getBytes("utf-8")); } catch (IOException e) { e.printStackTrace(); } } } }; Looper.loop(); } catch (IOException e) { e.printStackTrace(); Log.d("MainActivity",""); } } }
5.XML界面代码:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/tv_main" android:layout_width="match_parent" android:layout_height="match_parent" android:maxLines = "15" android:scrollbars = "vertical" android:background="@drawable/img_2" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignBottom="@id/tv_main" android:orientation="horizontal"> <EditText android:id="@+id/et_main" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <Button android:id="@+id/btn_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="send"/> </LinearLayout> </RelativeLayout>
6.最后一步,在AndroidMainfest。xml中添加这句话:
<uses-permission android:name="android.permission.INTERNET"/>
以下为试验结果:
out.println(data);//将键盘输入的服务端要发给客户端的数据封装在PrintWriter类的对象中
Sys