Android基于Socket的网络通讯
Socket又称“套接字”,应用程序通常通过“套接字”向网络发出请求或者应答网络请求。
在Java中,Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器
端,Socket是建立网络连接是调用的。在连接成功时,应用程序两端都会产生一个
Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是
平等的,并没有差别,不因为在服务器端或在客户端而产生不同的级别。不管是
Socket还是ServerSocket它们的工作都是通过Socket类及其子类完成的。
Socket链接的简历过程
1.服务器监听
2.客户端发出请求
3.简历链接
4.通信
Socket特点
1.Socket基于TCP链接,数据传输有保障
2.Socket适用于简历长时间链接
3.Socket编程通常应用于即时通讯
ServerSocket的建立与使用
创建一个java工程,新建一个MyServerSocket类:
public class MyServerSocket {
public static void main(String[] args){
try{
ServerSocket serverSocket = new ServerSocket(12345);
//block 阻塞
Socket socket = serverSocket.accept();
//建立连接
JOptionPane.showMessageDialog(null, "有客户端链接到了本机的12345端口");
}catch(IOException e){
e.printStackTrace();
}
}
}
运行程序没有弹出对话框是因为主线程被阻塞掉了,打开浏览器,地址栏中输入127.0.0.1:12345回车即可看到对话框
使用ServerSocket建立聊天服务器-1
创建一个java项目,首先新建一个ChatSocket类并且继承自Thread类:
public class ChatSocket extends Thread{
Socket socket;
public ChatSocket(Socket s){
this.socket = s;
}
public void out(String out){
try{
socket.getOutputStream.write(out.getBytes("UTF-8"));
}catch(Exception e){
e.printStackTrace();
}
}
public void run(){
int count = 0;
while(true){
count++;
out("loop:"+ count);
try{
sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
创建一个ServerListener类并且继承自Thread类,用于监听客户端的请求:
public class ServerListener extends Thread{
public void run(){
try{
ServerSocket serverSocket = new ServerSocket(12345);
while(true){
Socket socket = serverSocket.accept();
//建立连接
JOptionPane.showMessageDialog(null, "有客户端连接到本机的12345端口");
//将socket传递给新的线程
new ChatSocket(socket).start();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
在主类中:
public class MyServerSocket{
public static void main(String[] args){
new ServerListener().start();
}
}
打开终端(模仿客户端):输入telnet localhost 12345
以上的程序只能给客户端发送消息,不能接受客户端的请求信息,为完胜服务器的功能,
新建一个管理线程的类:
public class ChatManager{
private ChatManager(){}
private static final ChatManager cm = new ChatManager();
public static ChatManager getChatManager(){
return cm;
}
Vector<ChatSocket > vector = new Vector<ChatSocket>();
public void add(ChatSocket cs){
vector.add(cs);
}
public void publish(ChatSocket cs, String out){
for(int i = 0; i < vector.size(); i++){
ChatSocket csChatSocket = vector.get(i);
if(!cs.equals(csChatSocket)){
csChatSocket.out(out);
}
}
}
}
将以上的ServerListener类修改如下:
public class ServerListener extends Thread{
public void run(){
try{
ServerSocket serverSocket = new ServerSocket(12345);
while(true){
Socket socket = serverSocket.accept();
//建立连接
JOptionPane.showMessageDialog(null, "有客户端连接到本机的12345端口");
//将socket传递给新的线程
ChatSocket cs = new ChatSocket(socket);
cs.start();
ChatManager.getChatManager().add(cs);
}
}catch(Exception e){
e.printStackTrace();
}
}
}
因为ChatSocket中只有发送数据的功能,没有接受数据的功能,因此将其修改如下:
public class ChatSocket extends Thread{
Socket socket;
public ChatSocket(Socket s){
this.socket = s;
}
public void out(String out){
try{
socket.getOutputStream.write(out.getBytes("UTF-8"));
}catch(Exception e){
e.printStackTrace();
}
}
public void run(){
try{
BufferedReader br = new BufferedReader(new InputStreamReader(
socket.getInputStream(), "UTF-8"));
String line = null;
while((line = br.readLine()) != null){
ChatManager.getChatManager().publish(this, line);
}
br.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
再打开几个终端窗口,在各个终端中输入如:telnet localhost 12345 ,此时当你在任何一个窗口中输入一个语句的时候几个终端都同时显示输入的语句。
接下来创建一个Android客户端项目:
在xml中:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:layout_width="120dip"
android:layout_height="wrap_content"
android:id="@+id/edtIp"/>
<Button
android:layout_width="wrap_content"
android:text="连接"
android:layout_height="wrap_content"
android:onClick="connectIP"/>
</LinearLayout>
<TextView
android:id="@+id/showTv"
android:layout_width="fill_parent"
android:layout_height="360dip"/>
<EditText
android:id="@+id/sendEdit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<Button
android:layout_width="fill_parent"
android:text="发送"
android:layout_height="wrap_content"
android:onClick="sendClick"/>
MainActivity.java中:
private EditText edtIp;
private EditText sendEdit;
private TextView showTv;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edtIp = (EditText) findViewById(R.id.edtIp);
sendEdit = (EditText) findViewById(R.id.sendEdit);
showTv = (TextView) findViewById(R.id.showTv);
}
//点击事件
public void connectIP(View view){
connect();
}
public void sendClick(View view){
send();
}
Socket socket = null;
BufferedWriter writer = null;
BufferedReader reader = null;
public void connect(){
AsyncTask<Void, String, Void> read = new AsyncTask<Void, String, Void>(){
try{
socket = new Socket(ip.getText().toString(), 12345);
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
publishProgress("@success");
}catch(Exception e){
Toast.makeText(MainActivity.this, "无法建立链接", 1).show();
e.printStackTrace();
}
protected Void doInBackground(Void... arg0){
try{
String line;
while((line = reader.readLine()) != null){
publishProgress(line);
}
}catch(Exception e){
e.printStackTrace();
}
return null;
}
protected void onProgressUpdate(String... values){
if(values[0].equals("@success")){
Toast.makeText(MainActivity.this, "链接成功", 1).show();
}
showTv.append("服务器说:"+ values[0] + "\n");
super.onProgressUpdate(values);
}
}
read.execute();
}
public void send(){
try{
showTv.append("我说:"+ sendEdit.getText().toString() +"\n");
writer.write(sendEdit.getText().toString()+"\n");
writer.flush();
sendEdit.setText("");
}catch(Exception e){
e.printStackTrace();
}
}
记得添加网络权限,此时打开多个模拟器接口进行聊天。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步