Java实现简单的socket通信

原创 2013年12月05日 00:32:39

前言

首先,说一件无关的事情,萧鼎的诛仙2更新了,这一等就是一年啊,今天中午思考去阿里用神马花名的时候想起来google一下诛仙二,结果50多章都没看过,555,没忍住一下午全用来看小说了,罪过罪过

其次,就是今天学习了一下java如何实现socket通信,感觉难点反而是在io上,因为java对socket封装已经很完善了


参考

学习了一篇博客,写的不错,推荐给大家:http://cs.lmu.edu/~ray/notes/javanetexamples/#capitalize


代码

今天代码花了整个晚上调试,主要原因是io的flush问题和命令行下如何运行具有package的类,不过最后问题基本都解决了,把代码贴出来供大家参考

server

package socket;

import java.io.*;
import java.net.*;

public class TcpServer {
    public static void main(String[] args) throws Exception {
        ServerSocket server = new ServerSocket(9091);
        try {
            Socket client = server.accept();
            try {
                BufferedReader input =
                        new BufferedReader(new InputStreamReader(client.getInputStream()));
                boolean flag = true;
                int count = 1;

                while (flag) {
                    System.out.println("客户端要开始发骚了,这是第" + count + "次!");
                    count++;
                    
                    String line = input.readLine();
                    System.out.println("客户端说:" + line);
                    
                    if (line.equals("exit")) {
                        flag = false;
                        System.out.println("客户端不想玩了!");
                    } else {
                        System.out.println("客户端说: " + line);
                    }

                }
            } finally {
                client.close();
            }
            
        } finally {
            server.close();
        }
    }
}

client

package socket;

import java.io.*;
import java.net.*;
import java.util.Scanner;

public class TcpClient {
    public static void main(String[] args) throws Exception {
        Socket client = new Socket("127.0.0.1", 9091);
        try {
            PrintWriter output =
                    new PrintWriter(client.getOutputStream(), true);
            Scanner cin = new Scanner(System.in);
            String words;

            while (cin.hasNext()) {
                words = cin.nextLine();

                output.println(words);

                System.out.println("写出了数据: " + words);
            }

            cin.close();
        } finally {
            client.close();
        }
    }
}


Server绑定ip

用c写socket的时候,struct sockaddr_in 结构体是可以指定sin_addr.s_addr的,也就是可以指定ip地址,为什么会有这种需求呢,例如我的网络链接是这样的:



我可能只想绑定eth0这个网卡的ip地址,因为我的lo和wlan0都可能在用一端口做了nginx的虚拟主机,因此在服务器端开启ServerSocket的时候,有指定ip的需求


方案

ServerSocket的一个构造函数如下:

public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException

参数:
  • port - 本地 TCP 端口
  • backlog - 侦听 backlog
  • bindAddr - 要将服务器绑定到的 InetAddress

因为InetAddress无构造函数,我在这里纠结了好一段时间,查看stackoverflow上,可以使用InetAddress的getByName方法

示例代码

InetAddress bindip = InetAddress.getByName("192.168.1.168");

ServerSocket server = new ServerSocket(9091, 0, bindip);


并发访问

服务器端通过增加多线程来同时处理多个客户端的请求,其实实现还是很水的,毕竟java对多线程封装也足够好了,我是在Server服务器端用一个内部类实现了Runnable接口,在run方法里处理客户端的请求,将数据打印出来

server代码

package capitalsocket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class CapitalizeServer {
    private static int clientNum = 0;

    public static void main(String args[]) throws Exception {
        ServerSocket listener = new ServerSocket(9898, 0, InetAddress.getByName("192.168.1.168"));
        try {
            while (true) {
                Capitalizer multip = new Capitalizer(listener.accept(), CapitalizeServer.clientNum ++);
                Thread t = new Thread(multip);
                t.start();
            }
        } finally {
            listener.close();
        }
    }

    private static class Capitalizer implements Runnable {
        private Socket client;
        private int id;

        public Capitalizer(Socket s, int id) {
            this.client = s;
            this.id = id;
        }

        public void run() {
            try {
                BufferedReader input =
                        new BufferedReader(new InputStreamReader(this.client.getInputStream()));
                
                while (true) {
                    String data = input.readLine();
                    
                    if (data.equals("bye")) {
                        System.out.println("当前第" + this.id + "个客户端度不想玩了!");
                        break;
                    } else {
                        System.out.println("当前第" + this.id + "个客户端说:" + data);
                    }
                }

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    this.client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

client代码

客户端代码基本没变,增加了一个退出操作

package capitalsocket;

import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class CapitalizeClient {
    public static void main(String[] args) throws Exception {
        Socket client = new Socket("192.168.1.168", 9898);
        try {
            PrintWriter output = new PrintWriter(client.getOutputStream(), true);
            Scanner cin = new Scanner(System.in);
            String words;

            while (cin.hasNext()) {
                words = cin.nextLine();
                output.println(words);
                
                if (words.equals("bye")) {
                    break;
                }
                
                // 每写一次数据需要sleep一会
                Thread.sleep(3000);
            }

            cin.close();
        } finally {
            client.close();
        }
    }
}


吐槽

java的io还是有点复杂的,蛋疼
版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

一个 Java 的 Socket 服务器和客户端通信的例子

一个 HelloWord 级别的 Java Socket 通信的例子。通讯过程:         先启动 Server 端,进入一个死循环以便一直监听某端口是否有连接请求。然后运行 Client 端...

java Socket通信(一)

java socket通信已经被封装好了主要使用两个类ServerSocket 和Socket 首先写一个1v1的通信 服务端 /** * */ package com.dnion.s...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

Java--Socket通信(双向,有界面)

服务端: import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Toolkit; import jav...
  • zlQQhs
  • zlQQhs
  • 2013-04-04 14:18
  • 8832

java实现最简单socket通讯

一.服务器public class HServerApp implements Runnable { public int port; public HServerApp(int por...

java Socket(二)

上次做了一个java socket一对一通信的例子这次来写一个一对多的通信,这里我们使用java的多线程来实现 首先来看一下服务类 /** * */ package com.dnion.so...

Java--Socket通信(双向)

新建两个工程,一个客户端,一个服务端,先启动服务端再启动客户端 两个工程的读写操作线程类基本上完全相同     服务端:   import java.io.BufferedReader; ...
  • zlQQhs
  • zlQQhs
  • 2013-04-03 18:53
  • 30698

Java Socket简例

Socket io工具类: import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream;...

socket.io

.net版Socketio4net类库和java版socket.io-java-client类库 连接socket.io 1.4版本都不行,网上大多是socket.io 0.9版本的,socket.i...

构建实时Web的JAVA选择组合:socket.io client + socketio-netty server

构建实时Web的JAVA选择组合:socket.io client + socketio-netty server 前言 现在一说到实时web,可能大家不由自主的就想到了node.js,确...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)