NIO中的SocketChannel多次write之后 用read如何做到区分多次的数据

例如socketChannel.write(ByteBuffer) buteBuffer的长度可能随时变更,但是接收的时候read方法是以一个固定的长度接收的

发送方

byte[] outData = new byte[2048];
ByteBuffer outByteBuffer = ByteBuffer.wrap(outData);
toWriteNrBytes = 获取数据返回一个长度;
outByteBuffer.limit(toWriteNrBytes);
socketChannel.write(outByteBuffer);

接收方

byte[] inData = new byte[2048];
ByteBuffer inByteBuffer = ByteBuffer.wrap(inData);
readNrBytes = socketChannel.read(inByteBuffer);

可是这个readNrBytes并不能实时的到每次写入的长度,请问怎么解决

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
Java nio服务端对同一个消息多次select如何处理
服务端代码 ``` private void listen() throws IOException { SocketChannel client; while (selector.select() > 0) { System.out.println("select"); Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectionKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); //置空迭代器 keyIterator.remove(); try { if (key.isAcceptable()) { server = (ServerSocketChannel) key.channel(); client = server.accept(); client.configureBlocking(false); client.register(selector,SelectionKey.OP_READ); }else if (key.isReadable()) { System.out.println("read"); ByteBuffer readBuffer = ByteBuffer.allocate(1024); SocketChannel readChannel = (SocketChannel) key.channel(); readChannel.read(readBuffer); readBuffer.flip(); int i = readBuffer.getInt(); System.out.println("输出 " +i); } if (key.isWritable()) { } }catch (IOException e) { key.channel().close(); key.cancel(); } } } } ``` 客户端代码 ``` ByteBuffer writeBuffer = ByteBuffer.allocate(1024); writeBuffer.putInt(111); try { client.write(writeBuffer); } catch (IOException e) { e.printStackTrace(); } ``` 服务端输出3次select 其中一次是连接accept 一次是接收消息 还有一次呢? 另外 在另一个程序中 服务端不断地对同一个消息处理 大概6次直到报错(这个程序是持续连接 另起线程) 求助
java nio通信问题如何解决
大佬们帮我看看这句代码,我有点理解不了:![图片说明](https://img-ask.csdn.net/upload/201706/02/1496365514_646261.png) 这句代码的前面是获取欲与服务器端建立联系的selectionkey的作用,但是server.accept()这句代码并没有和相应的selectionkey对应,jdk只是说这句代码的作用只是获取此刻与服务器channel建立连接的socketchannel而不是此刻正在被检查的selectionkey的对应的socketchannel,那前面的那句sk.isAccpetable()不就起不到作用了吗?请知道的大侠告诉下。代码如下: public class NServer { //用于检测所有Channel状态的Selector private Selector selector=null; static final int PORT=3334; //定义实现编码、解码的字符集对象 private Charset charset=Charset.forName("UTF-8"); public void init() { try { selector=Selector.open(); //通过open方法来打开一个未绑定的ServerSocketChannel实例 ServerSocketChannel server=ServerSocketChannel.open(); InetSocketAddress isa=new InetSocketAddress("127.0.0.1",PORT); //将该ServerSocketChannel绑定到指定IP地址 server.bind(isa); //设置ServerSocket以非阻塞方式工作 server.configureBlocking(false); //将server注册到指定的Selector对象 server.register(selector,SelectionKey.OP_ACCEPT); while(true) //说明有需要处理的IO对象 { if(selector.select()==0)continue; //依次处理selector上的每个选择的SelectionKey for(SelectionKey sk :selector.selectedKeys()) { //从selector上的已选择Key集中删除正在处理的SelectionKey selector.selectedKeys().remove(sk); //如果sk对应的Channel包含客户端的连接请求 if(sk.isAcceptable()) { //调用accept方法接受连接,产生服务端的SocketChannel SocketChannel sc=server.accept(); //设置采用非阻塞模式 if (sc == null) { continue; } sc.configureBlocking(false); //将该SocketChannel也注册到selector //后面的read表示我们可以向通道那里读入数据了 // System.out.println("@@@@@@@@@@@@"); sc.register(selector, SelectionKey.OP_READ); //将sk对应的Channel设置成准备接收其他请求 //sk.interestOps(SelectionKey.OP_ACCEPT); } //如果sk对应的Channel有数据需要读取 if(sk.isReadable()) { //System.out.println("@@@@@@@@@@@@"); //获取该SelectionKey对应的Channel,该Channel中有可读的数据 SocketChannel sc=(SocketChannel) sk.channel(); //定义准备执行读取数据的ByteBuffer ByteBuffer buff=ByteBuffer.allocate(1024); String content=""; //开始读取数据 try { while(sc.read(buff)>0) { buff.flip(); content+=charset.decode(buff); } //打印从该sk对应的Channel里读取到的数据 while(sc.write(buff)>0) { buff.clear(); content+=charset.decode(buff); } //将sk对应的Channel设置成准备下一次读取 sk.interestOps(SelectionKey.OP_READ); System.out.println("Server收到信息了: "+content); if(content.length()<5) { sc.write(charset.encode("你发过来的长度小于5")); } else if(content.length()<9) { sc.write(charset.encode("你发过来的长度小于9")); } }catch(IOException ex) { //从Selector中删除指定的SelectionKey sk.cancel(); if(sk.channel()!=null) { sk.channel().close(); } } //sc.write(charset.encode(line)); } } } } catch (IOException e) { // TODO 自动生成的 catch 块 //System.out.println("出错了"); e.printStackTrace(); } } class Thread3 extends Thread { public void run() { init(); System.out.println("结束了"); } } public static void main(String[]args) { new NServer().new Thread3().start(); } }
java nio selector怎么达到与Linux select一样的效果
前几天做了一个linux下的socket实验使用了select,可以让程序在不使用多线程的情况下,实现io的异步,也就是可以收数据,也可以发数据,但不阻塞。 于是我就想能不能移植到Java下来实现。结果我发现Java也有select类似的功能,但是我发现Java nio的Chanel无法对标准输入进行处理,要发数据的时候就会阻塞。 可能是我技术不够,我想问问大家Java nio到底能不能实现与linux select一样的效果? package server; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Scanner; import java.nio.ByteBuffer; import java.nio.channels.Channel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; public class ServerSock { public ServerSock() { // TODO Auto-generated constructor stub try { ServerSocketChannel server= ServerSocketChannel.open(); server.bind(new InetSocketAddress(InetAddress.getLocalHost(), 8899), 5); System.out.println("服务器启动...."); Selector selector = Selector.open(); server.configureBlocking(false); server.register(selector, SelectionKey.OP_ACCEPT); ByteBuffer buf = ByteBuffer.allocate(48); SocketChannel channel = null; while(true){ int a=selector.select(); Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator(); while(keyIter.hasNext()){ SelectionKey key = keyIter.next(); if (key.isAcceptable()) { channel = server.accept(); System.out.println("接受: "); channel.configureBlocking(false); channel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE); }else if (key.isReadable()) { System.out.println("读取:"); int bytesRead = channel.read(buf); buf.flip(); String aString = new String(buf.array()).trim(); System.out.println(aString); buf.clear(); }else if (key.isWritable()) { System.out.println("写入:"); Scanner scanner = new Scanner(System.in); String b = scanner.nextLine(); buf.put(b.getBytes()); buf.flip(); channel.write(buf); buf.clear(); } keyIter.remove(); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { new ServerSock(); } } ``` ```
java nio selector.select不阻塞
# java nio selector.select不阻塞 java nio 构建的服务端在与客户端(用ubuntu虚拟机的netcat)连接上后, netcat直接ctrl + d(什么内容都不输入)的话,服务端的selector.select()方法的结果就一直是0 也不阻塞了。请问这是为什么。 代码如下: ```java package chapter4; import org.junit.Test; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Set; public class List4_2 { @Test public void test1(){ PlainNIOServer server = new PlainNIOServer(); try { server.serve(12345); } catch (IOException e) { e.printStackTrace(); } } private static class PlainNIOServer { public void serve(int port) throws IOException {//在对方连接上以后直接ctrl+d会陷入readable的死循环 ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel.configureBlocking(false); serverChannel.bind(new InetSocketAddress(port)); Selector selector = Selector.open(); serverChannel.register(selector, SelectionKey.OP_ACCEPT); while(true){ if (selector.select() == 0){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // continue; } Set<SelectionKey> keys = selector.selectedKeys(); Iterator<SelectionKey> it = keys.iterator(); while (it.hasNext()){ SelectionKey key = it.next(); it.remove(); System.out.println("acc : " + key.isAcceptable() + ", w : " + key.isWritable() + ", r : " + key.isReadable() + ", conn : " + key.isConnectable() + ", v : " + key.isValid()); try { if (key.isAcceptable()) { ServerSocketChannel server = (ServerSocketChannel) key.channel(); SocketChannel client = server.accept(); if (client != null) { client.configureBlocking(false); client.register(selector, SelectionKey.OP_READ); System.out.println("Accept Connection from " + client); } } if (key.isReadable()) { SocketChannel client = (SocketChannel) key.channel(); ByteBuffer byteBuffer = ByteBuffer.allocate(5); System.out.println("readable !!!"); int count = 0; while (( count = client.read(byteBuffer)) > 0 ) { byteBuffer.flip(); byte[] bytes = new byte[1024]; while (byteBuffer.hasRemaining()) { byteBuffer.get(bytes, 0, Math.min(byteBuffer.remaining(), bytes.length)); String sentence; System.out.println(sentence = new String(bytes, 0, count)); byteBuffer.compact(); byteBuffer.put(sentence.getBytes()); byteBuffer.flip(); client.write(byteBuffer); } byteBuffer.compact(); } } } catch (Exception e){ e.printStackTrace(); key.channel().close(); } } } } } } ``` 运行如上代码以后,在虚拟机里运行netcat , 截图如下 ![图片说明](https://img-ask.csdn.net/upload/201806/23/1529747149_870890.png) 此时在netcat中按下ctrl + d (EOF)则服务端的selector.select方法调用之后返回结果一直为0且不再阻塞,所有连上的客户端也没办法发消息了。 服务端效果如下: ![图片说明](https://img-ask.csdn.net/upload/201806/23/1529747418_255698.png)
java nio的select和linux的epoll有什么区别?
#### 最近在看关于epoll和select相关问题,但是并没有发现java的select和linux的epoll有什么区别 #### java的nio select代码如下 ``` import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.UUID; public class NioServer { private static Map<String, SocketChannel> clientMap = new HashMap<>(); public static void main(String[] args) throws IOException { ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); ServerSocket serverSocket = serverSocketChannel.socket(); serverSocket.bind(new InetSocketAddress(8899)); Selector selector = Selector.open(); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while (true) { try { /** * 程序会卡在select()函数,当客户端有动作了,比如连接上了,或者是发送消息过来了,服务端才会继续走 * 当第一个客户端连接上并且是selectionKey.isAcceptable(),代码就又重新卡到了select()函数上 * 等待客户端的再次操作(无论是哪个客户端) */ selector.select(); /** * selector.selectedKeys()这段代码可以从中知道是哪个客户端,执行了什么操作 * */ Set<SelectionKey> selectionKeys = selector.selectedKeys(); selectionKeys.forEach((selectionKey) -> { final SocketChannel client; try { if (selectionKey.isAcceptable()) { ServerSocketChannel server = (ServerSocketChannel) selectionKey.channel(); /** * 这代代码获取了真正的客户端socket句柄 */ client = server.accept(); client.configureBlocking(false); /** * 这句话如果不写,就相当于没有注册当消息可读时的回调函数,当客户端发送消息过来的时候 * 服务端的selector.selectedKeys()就永远不会受到这类消息 */ client.register(selector, SelectionKey.OP_READ); String key = "[" + UUID.randomUUID().toString() + "]"; clientMap.put(key, client); } else if (selectionKey.isReadable()) { client = (SocketChannel) selectionKey.channel(); ByteBuffer readBuffer = ByteBuffer.allocate(1024); int count = client.read(readBuffer); if (count > 0) { readBuffer.flip(); Charset charset = Charset.forName("utf-8"); String recvMsg = String.valueOf(charset.decode(readBuffer).array()); System.out.println(client + ":" + recvMsg); String sendKey = null; for (Map.Entry<String, SocketChannel> stringSocketChannelEntry : clientMap.entrySet()) { if (stringSocketChannelEntry.getValue() == client) { sendKey = stringSocketChannelEntry.getKey(); break; } } for (Map.Entry<String, SocketChannel> stringSocketChannelEntry : clientMap.entrySet()) { SocketChannel socketChannel = stringSocketChannelEntry.getValue(); ByteBuffer writeBuffer = ByteBuffer.allocate(1024); writeBuffer.put((sendKey + ": " + recvMsg).getBytes()); writeBuffer.flip(); socketChannel.write(writeBuffer); } } } } catch (Exception ex) { ex.printStackTrace(); } }); selectionKeys.clear(); } catch (Exception e) { e.printStackTrace(); } } } } ``` #### linux的epoll的c代码如下 ``` #include <iostream> #include <sys/socket.h> #include <sys/epoll.h> #include <netinet/in.h> #include <arpa/inet.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <errno.h> #include <cstring> using namespace std; #define MAXLINE 5 #define OPEN_MAX 100 #define LISTENQ 20 #define SERV_PORT 5000 #define INFTIM 1000 void setnonblocking(int sock) { int opts; opts=fcntl(sock,F_GETFL); if(opts<0) { perror("fcntl(sock,GETFL)"); exit(1); } opts = opts|O_NONBLOCK; if(fcntl(sock,F_SETFL,opts)<0) { perror("fcntl(sock,SETFL,opts)"); exit(1); } } int main(int argc, char* argv[]) { int i, maxi, listenfd, connfd, sockfd,epfd,nfds, portnumber; ssize_t n; char line[MAXLINE]; socklen_t clilen; if ( 2 == argc ) { if( (portnumber = atoi(argv[1])) < 0 ) { fprintf(stderr,"Usage:%s portnumber/a/n",argv[0]); return 1; } } else { fprintf(stderr,"Usage:%s portnumber/a/n",argv[0]); return 1; } //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件 struct epoll_event ev,events[20]; //生成用于处理accept的epoll专用的文件描述符 //创建一个epoll文件描述符 epfd=epoll_create(256); struct sockaddr_in clientaddr; struct sockaddr_in serveraddr; listenfd = socket(AF_INET, SOCK_STREAM, 0); //把socket设置为非阻塞方式 //setnonblocking(listenfd); //设置与要处理的事件相关的文件描述符 ev.data.fd=listenfd; //设置要处理的事件类型 ev.events=EPOLLIN|EPOLLET; //ev.events=EPOLLIN; //注册epoll事件,将socket文件描述符listenfd的ev事件注册到epoll上 epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); memset(&serveraddr, sizeof(serveraddr) ,0); serveraddr.sin_family = AF_INET; char *local_addr="127.0.0.1"; inet_aton(local_addr,&(serveraddr.sin_addr));//htons(portnumber); serveraddr.sin_port=htons(portnumber); //先bind再监听 bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr)); listen(listenfd, LISTENQ); maxi = 0; for ( ; ; ) { //等待epoll事件的发生 //param epfd表示将监听epfd的事件 //param events表示容器,一旦有事件发生,events数组会被填充 nfds=epoll_wait(epfd,events,20,500); //处理所发生的所有事件 for(i=0;i<nfds;++i) { if(events[i].data.fd==listenfd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。 { connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen); if(connfd<0){ perror("connfd<0"); exit(1); } //setnonblocking(connfd); char *str = inet_ntoa(clientaddr.sin_addr); cout << "accapt a connection from " << str << endl; //设置用于读操作的文件描述符 ev.data.fd=connfd; //设置用于注测的读操作事件 ev.events=EPOLLIN|EPOLLET; //ev.events=EPOLLIN; //注册ev epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); } else if(events[i].events&EPOLLIN)//如果是已经连接的用户,并且收到数据,那么进行读入。 { cout << "EPOLLIN" << endl; if ( (sockfd = events[i].data.fd) < 0) continue; if ( (n = read(sockfd, line, MAXLINE)) < 0) { if (errno == ECONNRESET) { close(sockfd); events[i].data.fd = -1; } else std::cout<<"readline error"<<std::endl; } else if (n == 0) { close(sockfd); events[i].data.fd = -1; } line[n] = '/0'; cout << "read " << line << endl; //设置用于写操作的文件描述符 ev.data.fd=sockfd; //设置用于注测的写操作事件 ev.events=EPOLLOUT|EPOLLET; //修改sockfd上要处理的事件为EPOLLOUT //epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); } else if(events[i].events&EPOLLOUT) // 如果有数据发送 { sockfd = events[i].data.fd; write(sockfd, line, n); //设置用于读操作的文件描述符 ev.data.fd=sockfd; //设置用于注测的读操作事件 ev.events=EPOLLIN|EPOLLET; //修改sockfd上要处理的事件为EPOLIN epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); } } } return 0; } ``` #### 从上面两段代码看好像基本思想都是一样的,并没有传说中的select不知道发生的事件,只能通过循环去判断的情况。 #### 但是后来我又在网上找了一段linux的select实现的网络io代码 ``` #include<stdio.h> #include<sys/types.h> #include<sys/socket.h> #include<unistd.h> #include<stdlib.h> #include<errno.h> #include<arpa/inet.h> #include<netinet/in.h> #include<string.h> #include<signal.h> #define MAXLINE 1024 #define LISTENLEN 10 #define SERV_PORT 6666 int main(int argc, char **argv) { int i, maxi, maxfd, listenfd, connfd, sockfd; int nready, client[FD_SETSIZE]; ssize_t n; fd_set rset, allset; char buf[MAXLINE]; socklen_t clilen; struct sockaddr_in cliaddr, servaddr; listenfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); bind(listenfd, (struct sockaddr*) &servaddr, sizeof(servaddr)); listen(listenfd, LISTENLEN); maxfd = listenfd; /* initialize */ maxi = -1; /* index into client[] array */ for (i = 0; i < FD_SETSIZE; i++) client[i] = -1; /* -1 indicates available entry */ FD_ZERO(&allset); FD_SET(listenfd, &allset); for ( ; ; ) { rset = allset; /* structure assignment */ nready = select(maxfd+1, &rset, NULL, NULL, NULL); if (FD_ISSET(listenfd, &rset)) /* new client connection */ { clilen = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr*) &cliaddr, &clilen); #ifdef NOTDEF printf("new client: %s, port %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, 4, NULL), ntohs(cliaddr.sin_port)); #endif for (i = 0; i < FD_SETSIZE; i++) if (client[i] < 0) { client[i] = connfd; /* save descriptor */ break; } if (i == FD_SETSIZE) { printf("too many clients"); exit(0); } FD_SET(connfd, &allset); /* add new descriptor to set */ if (connfd > maxfd) maxfd = connfd; /* for select */ if (i > maxi) maxi = i; /* max index in client[] array */ if (--nready <= 0) continue; /* no more readable descriptors */ } for (i = 0; i <= maxi; i++) /* check all clients for data */ { if ( (sockfd = client[i]) < 0) continue; if (FD_ISSET(sockfd, &rset)) { if ( (n = read(sockfd, buf, MAXLINE)) == 0)/* connection closed by client */ { close(sockfd); FD_CLR(sockfd, &allset); client[i] = -1; } else write(sockfd, buf, n); if (--nready <= 0) break; /* no more readable descriptors */ } } } } ``` #### 从这段代码里面确实是可以看出是通过循环判断的,我的问题是java的select是不是就是linux的epoll的思想?
java nio scoket的连接问题
下面是一个测试例子,主要是连接地址不同,请在注释的地方切换分别测试.希望能详细讲解一下这两个过程,特别是连127.0.0.1这个 1) InetSocketAddress addr = new InetSocketAddress("www.baidu.com", 80); 2) //InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 80); /** * NIO_baidu.java * * Version 1.0 * * 2014-1-16 * * Copyright www.wangjiu.com */ package com._0116; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; /** * TODO (描述类的功能) * * @author d * 2014-1-16 * */ public class NIO_baidu { /** * TODO (描述方法的作用) * * @param args * @throws Exception */ public static void main(String[] args) throws Exception { // 用下面两个连接地址分别测试 InetSocketAddress addr = new InetSocketAddress("www.baidu.com", 80); //InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 80); SocketChannel channel = SocketChannel.open(addr); System.out.println(); byte[] header = "GET / HTTP/1.1\r\nHost: www.baidu.com\r\n\r\n".getBytes(); ByteBuffer buf = ByteBuffer.allocate(header.length); buf.put(header); buf.flip(); channel.write(buf); buf = ByteBuffer.allocate(1024); int count = channel.read(buf); while(count != -1) { buf.flip(); while(buf.hasRemaining()){ System.out.print((char)buf.get()); } buf.clear(); count = channel.read(buf); System.out.print(count); } channel.close(); } } 第一个的返回结果是: 就是百度首页的html代码,太长了贴不下. ============= 第二个返回结果是: HTTP/1.1 200 OK Date: Fri, 17 Jan 2014 02:39:29 GMT Server: Apache/2.2.25 (Win32) Last-Modified: Sat, 20 Nov 2004 07:16:24 GMT ETag: "80c5b3c60-2c-3e94b66a46200" Accept-Ranges: bytes Content-Length: 44 Content-Type: text/html <html><body><h1>It works!</h1></body></html>
java nio SelectionKey isWritable为什么一直是true
服务器 [code="java"] package test.nio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.Iterator; import java.util.Set; public class NonBlockEchoServer { private ServerSocketChannel serverSocketChannel; private int port = 8992; private Selector selector; private Charset charset; public NonBlockEchoServer() throws IOException { charset = Charset.forName("UTF-8"); selector = Selector.open(); serverSocketChannel = ServerSocketChannel.open(); //可以绑定到同一个端口 serverSocketChannel.socket().setReuseAddress(true); //设置为非阻塞模式 serverSocketChannel.configureBlocking(false); serverSocketChannel.socket().bind(new InetSocketAddress(port)); } public void service() throws IOException { serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while(selector.select() > 0) { Set<SelectionKey> keys = selector.selectedKeys(); Iterator<SelectionKey> it = keys.iterator(); while(it.hasNext()) { SelectionKey key = null; try { key = it.next(); it.remove(); if(key.isAcceptable()) { ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel(); SocketChannel socketChannel = serverSocketChannel.accept(); socketChannel.configureBlocking(false); ByteBuffer byteBuffer = ByteBuffer.allocate(0); socketChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE, byteBuffer); } if(key.isReadable()) { read(key); } if(key.isWritable()) { write(key); } }catch (IOException e) { if(key != null) { try { key.cancel(); key.channel().close(); } catch (IOException e1) { e1.printStackTrace(); } } e.printStackTrace(); } } } } private void write(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); ByteBuffer byteBuffer = (ByteBuffer) key.attachment(); byteBuffer.flip(); String data = decode(byteBuffer); if(data.indexOf("\r\n") == -1) { return; } String outputData = data.substring(0, data.indexOf("\n")+1); System.out.println("--->" + outputData); ByteBuffer outputBuffer = encode("echo:" + outputData); while(outputBuffer.hasRemaining()) { socketChannel.write(outputBuffer); } ByteBuffer temp = encode(outputData); byteBuffer.position(temp.limit()); byteBuffer.compact(); if(outputData.equals("bye\r\n")) { key.cancel(); socketChannel.close(); System.out.println("链接已经关闭"); } } private void read(SelectionKey key) throws IOException { System.out.println("server read"); SocketChannel socketChannel = (SocketChannel) key.channel(); socketChannel.configureBlocking(false); ByteBuffer byteBuffer = (ByteBuffer) key.attachment(); ByteBuffer readBuff = ByteBuffer.allocate(32); socketChannel.read(readBuff); byteBuffer.limit(byteBuffer.capacity()); readBuff.flip(); byteBuffer.put(readBuff); } /** * 解码 * @param byteBuffer * @return */ private String decode(ByteBuffer byteBuffer) { CharBuffer charBuffer = charset.decode(byteBuffer); return charBuffer.toString(); } /** * 编码 * @param str * @return */ private ByteBuffer encode(String str) { return charset.encode(str); } public static void main(String[] args) throws IOException { NonBlockEchoServer nonServer = new NonBlockEchoServer(); nonServer.service(); } } [/code] 客户端 [code="java"] package test.nio; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.Iterator; import java.util.Set; public class NonBlockEchoClient { private SocketChannel socketChannel; private ByteBuffer sendBuffer = ByteBuffer.allocate(1024); private ByteBuffer receiveBuffer = ByteBuffer.allocate(1024); Charset charset = Charset.forName("utf-8"); private Selector selector; private int port = 8992; public NonBlockEchoClient() throws IOException { socketChannel = SocketChannel.open(); socketChannel.connect(new InetSocketAddress(port)); socketChannel.configureBlocking(false); System.out.println("与服务器链接成功"); selector = Selector.open(); } public static void main(String[] args) throws IOException { final NonBlockEchoClient non = new NonBlockEchoClient(); Thread client = new Thread(new Runnable() { @Override public void run() { non.receiveFromUser(); } }); client.start(); non.talk(); } private void talk() throws IOException { socketChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE); while(selector.select() > 0) { Set<SelectionKey> keys = selector.selectedKeys(); Iterator<SelectionKey> it = keys.iterator(); while(it.hasNext()) { SelectionKey key = it.next(); it.remove(); if(key.isReadable()) { receive(key); } if(key.isWritable()) { send(key); } } } } public void receiveFromUser() { try { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); String msg = null; while((msg = bufferedReader.readLine()) != null) { System.out.println(msg); synchronized (sendBuffer) { sendBuffer.put(encode(msg+"\r\n")); } if("bye".equals(msg)) { break; } } } catch(IOException e) { e.printStackTrace(); } } private void send(SelectionKey key) throws IOException { SocketChannel socketChannel = (SocketChannel) key.channel(); synchronized (sendBuffer) { sendBuffer.flip(); socketChannel.write(sendBuffer); sendBuffer.compact(); } } private void receive(SelectionKey key) throws IOException { System.out.println("client RECEIVE"); SocketChannel socketChannel = (SocketChannel) key.channel(); socketChannel.read(receiveBuffer); receiveBuffer.flip(); String receiveData = decode(receiveBuffer); if(receiveData.indexOf("\n") == -1) return; String outputData = receiveData.substring(0, receiveData.indexOf("\n") + 1); System.out.println("--->" + outputData); if(outputData.equals("echo:bye\r\n")) { key.cancel(); socketChannel.close(); selector.close(); System.exit(0); } ByteBuffer temp = encode(outputData); receiveBuffer.position(temp.limit()); receiveBuffer.compact(); } private String decode(ByteBuffer byteBuffer) { return charset.decode(byteBuffer).toString(); } private ByteBuffer encode(String str) { return charset.encode(str); } } [/code] 各位大侠,最近小弟在学习nio编程,遇到一个问题:客户端在连接服务器端成功后,没有进行任何操作,服务器端并没有触发 写事件 为什么key.isWritable()一直为true ??
关于NIO的疑问,NIO是单线程的,如果后台有比较耗时的操作,别的客户端不就连不进来了?
见下面代码的:Thread.sleep(400000)部分,这里暂停线程模拟耗时操作后,别的客户端就连接不上了 [code="java"] import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; /** * @author marlonyao<yaolei135@gmail.com> * */ public class EchoServer3 { public static int DEFAULT_PORT = 9898; interface Handler { void execute(Selector selector, SelectionKey key); } public static void main(String[] args) throws IOException { System.out.println("Listening for connection on port " + DEFAULT_PORT); Selector selector = Selector.open(); initServer(selector); while (true) { selector.select(); for (Iterator<SelectionKey> itor = selector.selectedKeys().iterator(); itor.hasNext();) { SelectionKey key = (SelectionKey) itor.next(); itor.remove(); Handler handler = (Handler) key.attachment(); handler.execute(selector, key); } } } private static void initServer(Selector selector) throws IOException, ClosedChannelException { ServerSocketChannel serverChannel = ServerSocketChannel.open(); ServerSocket ss = serverChannel.socket(); ss.bind(new InetSocketAddress(DEFAULT_PORT)); serverChannel.configureBlocking(false); SelectionKey serverKey = serverChannel.register(selector, SelectionKey.OP_ACCEPT); serverKey.attach(new ServerHandler()); } static class ServerHandler implements Handler { public void execute(Selector selector, SelectionKey key) { ServerSocketChannel server = (ServerSocketChannel) key.channel(); SocketChannel client = null; try { client = server.accept(); System.out.println("Accepted connection from " + client); } catch (IOException e) { e.printStackTrace(); return; } SelectionKey clientKey = null; try { client.configureBlocking(false); clientKey = client.register(selector, SelectionKey.OP_READ); clientKey.attach(new ClientHandler()); } catch (IOException e) { if (clientKey != null) clientKey.cancel(); try { client.close(); } catch (IOException ioe) { } } } } static class ClientHandler implements Handler { private ByteBuffer buffer; public ClientHandler() { buffer = ByteBuffer.allocate(100); } public void execute(Selector selector, SelectionKey key) { try { if (key.isReadable()) { readKey(selector, key); } else if (key.isWritable()) { writeKey(selector, key); } } catch (IOException e) { key.cancel(); try { key.channel().close(); } catch (IOException ioe) { } } } private void readKey(Selector selector, SelectionKey key) throws IOException { SocketChannel client = (SocketChannel) key.channel(); try { Thread.sleep(400000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } int n = client.read(buffer); if (n > 0) { buffer.flip(); key.interestOps(SelectionKey.OP_WRITE); // switch to OP_WRITE } } private void writeKey(Selector selector, SelectionKey key) throws IOException { System.out.println("is writable..."); SocketChannel client = (SocketChannel) key.channel(); client.write(buffer); if (buffer.remaining() == 0) { // write finished, switch to OP_READ buffer.clear(); key.interestOps(SelectionKey.OP_READ); } } } } [/code]
java NIO 多线程
<div class="iteye-blog-content-contain" style="font-size: 14px;"> <pre name="code" class="java">public void run() { exitRequest = false ; while( !exitRequest) { try { // 初期化 socketChannel = SocketChannel.open() ; selector = Selector.open() ; socketChannel.socket().setReuseAddress( true) ; socketChannel.configureBlocking( false) ; socketChannel.socket().setReceiveBufferSize( RECV_BUFFER) ; selectionKey = socketChannel.register( selector, SelectionKey.OP_CONNECT) ; selectionKey.attach( new SocketNioControl( notifyObject, selector, socketChannel, selectionKey)) ; socketChannel.connect( inetAddress) ; int timer = 0 ; while( !socketChannel.isConnected()) { selector.select(100) ; if( exitRequest) { break ; } for( SelectionKey key : selector.selectedKeys()) { if( key.isConnectable()) { SocketChannel socketChannel = ( SocketChannel)key.channel() ; SocketNioControl socketControl = ( SocketNioControl)key.attachment() ; socketChannel.finishConnect() ; key.interestOps( SelectionKey.OP_READ) ; socketControl.connect() ; break ; } } if( timer &gt;= TIMER_CONNECT * 1000) { throw new ConnectException() ; } timer += 100 ; } try { while( !exitRequest) { selector.select() ; for( SelectionKey key : selector.selectedKeys()) { SocketNioControl socketControl = ( SocketNioControl)key.attachment() ; if( key.isReadable()) { socketControl.read() ; } if( key.isWritable()) { socketControl.write() ; } } } } catch ( ConnectException ioex) { } catch ( CancelledKeyException ckex) { } } catch ( UnknownHostException uhex) { ErrorMessage.logging( uhex) ; } catch ( Exception ex) { ErrorMessage.logging( ex) ; } finally { try { for( SelectionKey key : selector.keys()) { SocketNioControl socketControl = ( SocketNioControl)key.attachment() ; socketControl.disconnect() ; } if( selector != null) { selector.close() ; selector = null ; } for( int timer = 0; timer &lt; TIMER_RETRY * 1000; timer += 100) { Thread.sleep( 100) ; if( exitRequest) { break ; } } } catch( IOException ioe) { } catch( InterruptedException iex) { } } } }</pre> <p> 线程一直被占用,导致系统hungup.是哪里出问题呢?另外<span style="font-family: monospace; font-size: 1em; line-height: 1.5;"> selector.select() 的值一直是0;</span><span style="font-family: monospace; font-size: 1em; line-height: 1.5;">这一句是起什么作用的?</span></p> </div>
java 关于NIO实现UDP数据传输问题 ,急谢谢,C币不足请不要介意
各位大侠好,小弟想问一下问题,搞了一两天没有搞明白的。因为要实现一个UDP传输服务端,于是在网上找了很多资料然后就写了一个。但是写好之后发现有两个很严重的问题,希望各位大哥给点意见或者思路去解决。 问题一:启动服务端,同时也启动客户端,客户端传输数据服务器正常接收,但是断开客户端后,再启动客户端,服务器就收不到任何客户端发送的消息,好像是服务器关闭了UDP一样,但是重启服务器后(重新打开UDP)客户端既可以发送信息过来。 问题二:多个客户端。第一个客户端连接上后,第二个客户端怎么也链接不上了。即使关闭了第一个客户端也一样。 如下是代码: package com.gateway.socket; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.Iterator; import java.util.Set; import org.apache.log4j.Logger; public class UDPEchoServerSelector extends Thread { private static final Logger log = Logger.getLogger(ServerSocket.class); // private InetSocketAddress inetSocketAddress; // socket处理类 private UDPSocketHandler handler = new UDPSocketHandler(); // 注册的接受服务 private SocketReceiver receiver = null; /** * 初始化socket * * @param receiver * @param hostname * @param port * @throws IOException * @throws UnknownHostException */ public UDPEchoServerSelector(SocketReceiver receiver, String hostname, int port) { if (hostname.isEmpty()) { inetSocketAddress = new InetSocketAddress(port); } else { inetSocketAddress = new InetSocketAddress(hostname, port); } this.receiver = receiver; } @Override public void run() { try { Selector selector = Selector.open(); // 创建选择器,可以处理多路通道。 DatagramChannel serverSocketChannel = DatagramChannel.open(); // 打开通道 serverSocketChannel.configureBlocking(false); // 非阻塞 serverSocketChannel.socket().bind(inetSocketAddress); /* * 将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_READ事件,注册该事件后, * 当该事件到达时,selector.select()会返回,如果该事件没到达selector.select()会一直阻塞。 */ serverSocketChannel.register(selector, SelectionKey.OP_READ, new ClientData()); log.info("Server: socket server started."); /* * 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理 */ while (true) { // 轮询 // 当注册的事件到达时,方法返回;否则,该方法会一直阻塞 int nKeys = selector.select(); if (nKeys == 0) { continue; } // 得到选择键列表 Set Keys = selector.selectedKeys(); Iterator it = Keys.iterator(); while (it.hasNext()) { SelectionKey key = null; key = (SelectionKey) it.next(); // 键为位掩码 it.remove(); // 客户端请求连接事件 if (key.isValid() && key.isWritable()) { log.info("Server: SelectionKey is acceptable."); handler.handleWrite(key); } if (key.isReadable()) {// 获得了可读的事件 log.info("Server: SelectionKey is readable."); handler.receiveMsg(key, receiver); } } Keys.clear(); } } catch (IOException e) { e.printStackTrace(); } } public static class ClientData { public SocketAddress clientAddress; public ByteBuffer buffer = ByteBuffer.allocate(255); } } package com.gateway.socket; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.SelectionKey; import org.apache.log4j.Logger; import com.gateway.common.DeviceDataTools; import com.gateway.common.data.HexUtils; import com.gateway.socket.UDPEchoServerSelector.ClientData; /** * * 处理socket类 * * @author Andy * */ public class UDPSocketHandler { private static Logger log = Logger.getLogger(UDPSocketHandler.class); /** * 链接请求 * * @throws IOException */ public void handleWrite(SelectionKey key) { try { DatagramChannel channel = (DatagramChannel) key.channel(); ClientData clntDat = (ClientData) key.attachment(); clntDat.buffer.flip(); // 从起始位置开始发送 int bytesSent; bytesSent = channel.send(clntDat.buffer, clntDat.clientAddress); if (bytesSent != 0) { key.interestOps(SelectionKey.OP_READ); // 关注客户端发送数据 } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 读请求 * * @throws IOException */ public void receiveMsg(SelectionKey key, SocketReceiver receiver) { ByteBuffer byteBuffer = ByteBuffer.allocate(1024); byteBuffer.clear(); DatagramChannel socketChannel = (DatagramChannel) key.channel(); //非阻塞 try { socketChannel.configureBlocking(false); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } System.out.println("channel code:" + socketChannel.hashCode()); try { while (true) { InetSocketAddress client = (InetSocketAddress) socketChannel .receive(byteBuffer); byteBuffer.flip(); // byteBuffer中传过来的是10进制的bytep[] byte[] dst = new byte[byteBuffer.limit()]; byteBuffer.get(dst); // 将10进制的byte[]转化成16进制字符串 String data = HexUtils.converBytesToHex(dst); System.out.println(data); log.info("Server: data1 = " + data); byteBuffer.clear(); receiver.udpreceive(socketChannel, data, client); break; } } catch (java.io.IOException e) { //e.printStackTrace(); //this.closeChannel(key, socketChannel); } catch (Exception e) { //e.printStackTrace(); //this.closeChannel(key, socketChannel); } } /** * * @param socketChannel */ private void closeChannel(SelectionKey key, DatagramChannel socketChannel) { try { while (socketChannel.isOpen()) { key.cancel(); socketChannel.close(); } } catch (IOException e1) { e1.printStackTrace(); } } /** * 根据socketKey从内存中获取channel,通过channel向client端发送消息 * * @param socketKey * 内存在channel对应的key * @param data * 发送的数据 * @return * @throws IOException */ public static boolean send(String socketKey, String data) throws IOException { DatagramChannel socketChannel = SocketChannelMapper .getUDPChannel(socketKey); if (socketChannel == null || !socketChannel.isOpen()) { return false; } InetSocketAddress client = SocketChannelMapper .getUDPInetSocketAddress(socketKey + "address"); boolean f = socketChannel.isConnected(); ByteBuffer byteBuffer = ByteBuffer.wrap(DeviceDataTools.hex2Byte(data)); if (f) { socketChannel.write(byteBuffer); } else { socketChannel.connect(new InetSocketAddress(client.getAddress(), client.getPort())); socketChannel.send(byteBuffer, client); } return true; } /** * 根据socketKey从内存中获取channel,通过channel向client端发送消息 * * @param socketKey * 内存在channel对应的key * @param data * 发送的数据 * @return * @throws IOException */ public static boolean send(DatagramChannel socketChannel, String data, InetSocketAddress client) throws IOException { if (socketChannel == null) { return false; } System.out.println("#########################ADDRESS" + client.getAddress()); System.out.println("#########################PORT" + client.getPort()); boolean f = socketChannel.isConnected(); ByteBuffer byteBuffer = ByteBuffer.wrap(DeviceDataTools.hexStr2ByteArray(data)); if (f) { socketChannel.write(byteBuffer); } else { socketChannel.connect(new InetSocketAddress(client.getAddress(), client.getPort())); socketChannel.send(byteBuffer, client); } return true; } }
java NIO通信 客户端为什么收不到数据
客户端程序 public class NioSelectorClient { public static void main(String[] args) throws IOException{ SocketChannel channel = SocketChannel.open(); channel.configureBlocking(false); Selector selector = Selector.open(); channel.connect(new InetSocketAddress("127.0.0.1", 7777)); channel.register(selector,SelectionKey.OP_CONNECT|SelectionKey.OP_READ); System.out.println("============读===AAAA======"); while(true) { int n = selector.select(); if(n==0) continue; Iterator<SelectionKey> iter = selector.selectedKeys().iterator(); while(iter.hasNext()){ SelectionKey key = iter.next(); if(key.isConnectable()) { System.out.println("================连接成功了==============="); } if( key.isReadable()) { System.out.println("=========数据来了============"); SocketChannel client = (SocketChannel)key.channel(); ByteBuffer buf = ByteBuffer.allocate(1024); int a= client.read(buf); buf.flip(); byte[] b = new byte[a]; System.arraycopy(buf.array(), 0, b, 0, a); String s = new String(b); System.out.println("============读描述符有数据了======服务器发来的数据:"+s); } iter.remove(); } } } } 服务端程序 public class NioSelectorServer { public static void main(String[] args) throws IOException { // 创建一个selector选择器 Selector selector = Selector.open(); SocketChannel clientchannel = null; // 打开一个通道 ServerSocketChannel serverchannel = ServerSocketChannel.open(); // 使设定non-blocking的方式。 serverchannel.configureBlocking(false); serverchannel.socket().bind(new InetSocketAddress(7777)); // 向Selector注册Channel及我们有兴趣的事件 serverchannel.register(selector, SelectionKey.OP_ACCEPT); while(true) { int n = selector.select(); if (n != 0) { Iterator<SelectionKey> it = selector.selectedKeys().iterator(); while (it.hasNext()) { SelectionKey key = (SelectionKey) (it.next()); if (key.isAcceptable()) { System.out.println("=====服务端========连接了======="); ServerSocketChannel Serverchannel = (ServerSocketChannel) key.channel(); clientchannel = Serverchannel.accept(); clientchannel.configureBlocking(false); clientchannel.register(selector, SelectionKey.OP_WRITE); } if(key.isWritable()) { System.out.println("=============服务端===========可写========="); SocketChannel client = (SocketChannel) key.channel(); String ss = "客户端 你好"; client.write(ByteBuffer.wrap(ss.getBytes())); } it.remove(); } } } } } 在本地运行 为什么客户端一直收不到服务端发来的数据了,到底程序错在哪了 ,请大家帮忙指点,最好将我的错误代码改正过来,万分感谢!!!
java这个简单的服务器我要如何读取客户端的输入信息?
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import java.util.Set; public class EchoServer { public static int DEFAULT_PORT = 7; public static String text=""; public static ServerSocketChannel server; public static SocketChannel client ; public static ByteBuffer output ; public static void main(String[] args){ int port; try{ port = Integer.parseInt(args[0]); }catch(RuntimeException ex){ port = DEFAULT_PORT; } System.out.println("Listening for connertions on port "+port); ServerSocketChannel serverChannel; Selector selector; try{ serverChannel = ServerSocketChannel.open(); ServerSocket ss = serverChannel.socket(); InetSocketAddress address = new InetSocketAddress(port); ss.bind(address); serverChannel.configureBlocking(false); selector =Selector.open(); serverChannel.register(selector, SelectionKey.OP_ACCEPT); }catch(IOException ex){ ex.printStackTrace(); return; } while(true){ try{ selector.select(); }catch(IOException ex){ ex.printStackTrace(); break; } Set<SelectionKey> readyKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = readyKeys.iterator(); while(iterator.hasNext()){ SelectionKey key = iterator.next(); iterator.remove(); try{ if(key.isAcceptable()){ ServerSocketChannel server = (ServerSocketChannel) key.channel(); SocketChannel client = server.accept(); System.out.println("Accepted connection from "+client); client.configureBlocking(false); SelectionKey clientKey = client.register(selector, SelectionKey.OP_WRITE|SelectionKey.OP_READ); ByteBuffer buffer = ByteBuffer.allocate(100); clientKey.attach(buffer); } if(key.isReadable()){ client =(SocketChannel)key.channel(); output = (ByteBuffer)key.attachment(); client.read(output); output.flip(); Charset charset = Charset.forName("UTF-8"); CharsetDecoder decoder = charset.newDecoder(); CharBuffer charBuffer = null; charBuffer = decoder.decode(output); text=charBuffer.toString(); //if(text.equals("time")) //{ //System.out.println("2"); Date date=new Date(); DateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String time=format.format(date); byte b[] = time.getBytes(); //将十六进制字符串转换成十进制整数 //int i=Integer.decode(time); //创建一个大小为1的字节缓冲区因为只放一个byte值 ByteBuffer bb=ByteBuffer.allocate(1); //将十进制整数转换成二进制byte值然后存进ByteBuffer //bb.put(b); //打印ByteBuffer中的byte值 //byte []b1=bb.array(); client.write(output); // output.compact(); //} // text=output.toString(); //System.out.println(text); //output.compact(); } if(key.isWritable()){ client = (SocketChannel) key.channel(); output = (ByteBuffer)key.attachment(); //output.flip(); client.write(output); //output.compact(); } }catch(IOException ex){ key.cancel(); try{ key.channel().close(); }catch(IOException cex){} } } } } } 这是我写的,中间有点乱,因为客户在cmd访问我的服务器如果他输入time,我要给他返回时间。。。大神求助!!
java nio为什么会在Selector.select()函数一直等待
``` while (true) { // 选择一组键 selector.select(); // 返回此选择器的已选择键集 Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); // 遍历对应的 SelectionKey 处理 while (iterator.hasNext()) { SelectionKey selectionKey = (SelectionKey) iterator.next(); iterator.remove(); if(!selectionKey.isValid()){ continue; } // 判断此键的通道是否已完成其套接字连接操作 if (selectionKey.isConnectable()) { connected(selectionKey); } // 判断是否连接可读操作 else if (selectionKey.isReadable()) { readMessage(selectionKey); } // 判断是否连接可写操作 else if (selectionKey.isWritable()) { writeMessage(selectionKey); } } selectionKeys.clear(); } ``` ``` private void connected(SelectionKey selectionKey) throws IOException { SocketChannel client = (SocketChannel) selectionKey.channel(); // 判断该通道是否进行连接过程、完成连接过程 if (client.isConnectionPending()) { if (client.finishConnect()) { client.write("hello"); // 将数据写入该通道 client.register(selector, SelectionKey.OP_READ); } } } ``` 代码如上,为什么每次,执行connected(SelectionKey selectionKey) 过后循环到selector.select();后就一直等待?
非阻塞通信的问题
运行服务器后,在运行客户端, 服务器就挂了, 然后客户端一直循环显示 客户端可读... 客户端可写... 客户端可读... 客户端可写... 客户端可读... 客户端可写... 服务器端显示 Serve 启动了! 服务器端接收到连接... Exception in thread "main" 客户端信息/192.168.1.76:4634 java.nio.channels.IllegalBlockingModeException at java.nio.channels.spi.AbstractSelectableChannel.register(Unknown Source) at nonblock.MyServer.server(MyServer.java:40) at nonblock.MyServer.main(MyServer.java:55) 请问这是怎么回事啊? 谢谢了啊 这个是服务器端的代码 [code="java"]package nonblock; import java.io.*; import java.nio.*; import java.nio.channels.*; import java.nio.charset.*; import java.net.*; import java.util.*; public class MyServer { private ServerSocketChannel ssc ; private Selector selector ; private int port = 8000; private Charset charset ; public MyServer() throws IOException{ selector = Selector.open(); ssc = ServerSocketChannel.open(); ssc.socket().setReuseAddress(true); ssc.configureBlocking(false); ssc.socket().bind(new InetSocketAddress(port)); System.out.println("Serve 启动了!"); } public void server() throws IOException{ ssc.register(selector, SelectionKey.OP_ACCEPT); while(selector.select()>0){ Set keySet = selector.selectedKeys(); Iterator iter = keySet.iterator(); while(iter.hasNext()){ SelectionKey key = (SelectionKey)iter.next(); //一定要remove,否则会一直存在 iter.remove(); if(key.isAcceptable()){ ServerSocketChannel s = (ServerSocketChannel)key.channel(); SocketChannel sc = (SocketChannel)s.accept(); System.out.println("服务器端接收到连接..."); System.out.println("客户端信息"+sc.socket().getLocalAddress()+":"+sc.socket().getPort()); ByteBuffer buffer = ByteBuffer.allocate(1024); sc.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE, buffer); System.out.println("服务器完成注册..."); } if(key.isReadable()){ System.out.println("服务器端可以读取信息..."); } if(key.isWritable()){ System.out.println("服务器端可以写入信息..."); } } } } public static void main(String[] arg){ try { new MyServer().server(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } [/code] 这个是客户端的代码 [code="java"]package nonblock; import java.net.*; import java.nio.channels.*; import java.nio.*; import java.io.*; import java.nio.charset.*; import java.util.*; public class MyClient { private SocketChannel socketChannel = null; private ByteBuffer sendBuffer = ByteBuffer.allocate(1024); private ByteBuffer receiveBuffer = ByteBuffer.allocate(1024); private Charset charset = Charset.forName("GBK"); private Selector selector; public MyClient() throws IOException { socketChannel = SocketChannel.open(); InetAddress ia = InetAddress.getLocalHost(); InetSocketAddress isa = new InetSocketAddress(ia, 7676); socketChannel.connect(isa); socketChannel.configureBlocking(false); System.out.println("与服务器的连接建立成功"); selector = Selector.open(); } public static void main(String args[]) throws IOException { final MyClient client = new MyClient(); // Thread receiver = new Thread() { // public void run() { // client.receiveFromUser(); // } // }; // // receiver.start(); client.talk(); } private void talk() throws IOException { // TODO Auto-generated method stub socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE); while(selector.select()>0){ Set keySet = selector.selectedKeys(); Iterator iter = keySet.iterator(); while(iter.hasNext()){ SelectionKey key = (SelectionKey)iter.next(); iter.remove(); if(key.isReadable()){ System.out.println("客户端可读..."); } if(key.isWritable()){ System.out.println("客户端可写..."); } } } } } [/code]
Socket编程java.net.BindException: Address already in use: JVM_Bind
本人最近想学Socket编程:无奈遇到个问题.不知道是啥原因,还请各位不吝赐教. 问题是这样的:我想用Socket在服务端读取文本文件,第一次运行的时候,什么都没数出来,(不停止第一次开启的服务)第二次输出了文本内容,却报了个地址被占用的错.这是为什么呢? Socket客户端: package socket; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; import java.nio.channels.SocketChannel; public class socketClient { private String ip; public socketClient() { // TODO Auto-generated constructor stub } public socketClient(String ip){ this.ip=ip; } public void client(){ PrintWriter print=null; BufferedReader read=null; File file=null; try { Socket ket=new Socket(ip,9000);//与服务器取得链接. file=new File("e:\\我的地址.txt"); read=new BufferedReader(new InputStreamReader(new FileInputStream(file))); String readLine=null; print=new PrintWriter(ket.getOutputStream(),true); while((readLine=read.readLine())!=null){ print.print(readLine); } } catch (Exception e) { e.printStackTrace(); }finally{ try { read.close(); print.close(); } catch (IOException e) { e.printStackTrace(); } } } } Socket服务器: package socket; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class SocketRemot { private Map map=new HashMap(); public void reMoteRun(){ BufferedReader read=null; PrintWriter write=null; try { while(true){ ServerSocket soc=new ServerSocket(9000);//为服务器Socket指定端口 Socket socket=soc.accept();//服务器端阻塞,一直等待客户端来访问. map.put(socket.getPort()+"",socket); System.out.println("我在等待......."); //读取客户端文件. //得到socket读取文件的流//字节流 /* * InputStream是用于读取二进制文件的流,而服务器端读取的文件很有可能是文本形式的.所以要转换为字符流 * 字节流和字符流之间的转换通过InputStreamReader,和OutputStreamWrite来转换. */ read=new BufferedReader(new InputStreamReader(socket.getInputStream()));//获取读文件的字符流 write=new PrintWriter(socket.getOutputStream(),true);//通过现有的output流来创建新的printWrite流 System.out.println(read.readLine()); // String str=null; // while((str=read.readLine())!=null){ // System.out.println(read.readLine());//边读边写. // } // write.close(); // read.close(); // socket.close(); } } catch (IOException e) { e.printStackTrace(); }finally{ try { if(read!=null){ read.close(); } if(write!=null){ write.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void closeSocket(){ Iterator tor=map.values().iterator(); while(tor.hasNext()){ Socket soc=(Socket)tor.next(); if(!soc.isClosed()){ try { soc.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } Test: package socket; import java.net.InetAddress; import java.net.UnknownHostException; public class Test { public static void main(String[] args) { SocketRemot remot=new SocketRemot(); socketClient ket=new socketClient(getAddIp()); remot.reMoteRun(); ket.client(); remot.closeSocket(); } public static String getAddIp(){ String serverIp=null; try { serverIp = InetAddress.getLocalHost().toString(); serverIp = serverIp.substring(serverIp.indexOf("/")+1); System.out.println(serverIp); } catch (UnknownHostException e) { e.printStackTrace(); } return serverIp; } } error: java.net.BindException: Address already in use: JVM_Bind at java.net.DualStackPlainSocketImpl.bind0(Native Method) at java.net.DualStackPlainSocketImpl.socketBind(Unknown Source) at java.net.AbstractPlainSocketImpl.bind(Unknown Source) at java.net.PlainSocketImpl.bind(Unknown Source) at java.net.ServerSocket.bind(Unknown Source) at java.net.ServerSocket.<init>(Unknown Source) at java.net.ServerSocket.<init>(Unknown Source) at socket.SocketRemot.reMoteRun(SocketRemot.java:25) at socket.Test.main(Test.java:10)
关于java 实现socket的异步通信
我在网上也找到一个例子,但是没有客户端,我自己写了一个用ServerSocket连的客户端,但是连接上后不能写也不能读,不知道怎么回事,请高手解决。最好能给一个简单异步编程的例子。 下面是代码: package org.scorpion.scoket; /** * * @author chenjd */ import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.util.HashMap; import java.util.Iterator; import java.util.Set; public class NBServer { int port = 8090; int BUFFERSIZE = 1024; Selector selector = null; ServerSocketChannel serverChannel = null; HashMap clientChannelMap = null;// 用来存放每一个客户连接对应的套接字和通道 public NBServer(int port) { this.clientChannelMap = new HashMap(); this.port = port; } public void initialize() throws IOException { // 初始化,分别实例化一个选择器,一个服务器端可选择通道 this.selector = Selector.open(); this.serverChannel = ServerSocketChannel.open(); this.serverChannel.configureBlocking(false); InetAddress localhost = InetAddress.getLocalHost(); InetSocketAddress isa = new InetSocketAddress(localhost, this.port); this.serverChannel.socket().bind(isa);// 将该套接字绑定到服务器某一可用端口 } // 结束时释放资源 public void finalize() throws IOException { this.serverChannel.close(); this.selector.close(); } // 将读入字节缓冲的信息解码 public String decode(ByteBuffer byteBuffer) throws CharacterCodingException { Charset charset = Charset.forName("ISO-8859-1"); CharsetDecoder decoder = charset.newDecoder(); CharBuffer charBuffer = decoder.decode(byteBuffer); String result = charBuffer.toString(); return result; } // 监听端口,当通道准备好时进行相应操作 public void portListening(String data) throws IOException, InterruptedException { // 服务器端通道注册OP_ACCEPT事件 SelectionKey acceptKey = this.serverChannel.register(this.selector, SelectionKey.OP_ACCEPT); // 当有已注册的事件发生时,select()返回值将大于0 while (acceptKey.selector().select() > 0) { System.out.println("event happened"); // 取得所有已经准备好的所有选择键 Set readyKeys = this.selector.selectedKeys(); // 使用迭代器对选择键进行轮询 Iterator i = readyKeys.iterator(); while (i.hasNext()) { SelectionKey key = (SelectionKey) i.next(); i.remove();// 删除当前将要处理的选择键 if (key.isAcceptable()) {// 如果是有客户端连接请求 System.out.println("more client connect in!"); ServerSocketChannel nextReady = (ServerSocketChannel) key .channel(); // 获取客户端套接字 Socket s = nextReady.accept().socket(); // 设置对应的通道为异步方式并注册感兴趣事件 s.getChannel().configureBlocking(false); SelectionKey readWriteKey = s.getChannel().register( this.selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE); // 将注册的事件与该套接字联系起来 readWriteKey.attach(s); // 将当前建立连接的客户端套接字及对应的通道存放在哈希表//clientChannelMap中 this.clientChannelMap.put(s, new ClientChInstance(s .getChannel())); } else if (key.isReadable()) {// 如果是通道读准备好事件 System.out.println("Readable"); // 取得选择键对应的通道和套接字 SelectableChannel nextReady = (SelectableChannel) key .channel(); Socket socket = (Socket) key.attachment(); // 处理该事件,处理方法已封装在类ClientChInstance中 this.readFromChannel(socket.getChannel(), (ClientChInstance) this.clientChannelMap .get(socket)); } else if (key.isWritable()) {// 如果是通道写准备好事件 System.out.println("writeable"); // 取得套接字后处理,方法同上 Socket socket = (Socket) key.attachment(); SocketChannel channel = (SocketChannel) socket.getChannel(); // this.writeToChannel(channel, "This is from server!"); this.writeToChannel(channel, data); } } } } // 对通道的写操作 public void writeToChannel(SocketChannel channel, String message) throws IOException { ByteBuffer buf = ByteBuffer.wrap(message.getBytes()); int nbytes = channel.write(buf); } // 对通道的读操作 public void readFromChannel(SocketChannel channel, ClientChInstance clientInstance) throws IOException, InterruptedException { ByteBuffer byteBuffer = null; try{ byteBuffer = ByteBuffer.allocate(BUFFERSIZE); int nbytes = channel.read(byteBuffer); }catch(Exception e){ clientChannelMap.remove(channel.socket()); channel.close(); e=null; return; } byteBuffer.flip(); String result = this.decode(byteBuffer); // 当客户端发出”@exit”退出命令时,关闭其通道 if (result.indexOf("@exit") >= 0||result.indexOf("q")>=0) { channel.close(); } // else if(result.indexOf("@close") >= 0){//关闭服务 // channel.close(); // this.finalize(); // } else { clientInstance.append(result.toString()); // 读入一行完毕,执行相应操作 if (result.indexOf("\n") >= 0) { System.out.println("client input" + result); clientInstance.execute(); } } } // 该类封装了怎样对客户端的通道进行操作,具体实现可以通过重载execute()方法 public class ClientChInstance { SocketChannel channel; StringBuffer buffer = new StringBuffer(); public ClientChInstance(SocketChannel channel) { this.channel = channel; } public void execute() throws IOException { String message = "This is response after reading from channel!"; writeToChannel(this.channel, message); buffer = new StringBuffer(); } // 当一行没有结束时,将当前字窜置于缓冲尾 public void append(String values) { buffer.append(values); } } // 主程序 public static void main(String[] args) { NBServer nbServer = new NBServer(8090); try { nbServer.initialize(); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } try { nbServer.portListening("This is from server!"); } catch (Exception e) { e.printStackTrace(); } } } 我写的客户端: package org.scorpion.scoket; import java.io.OutputStream; import java.net.Socket; public class TCPClient { public static void main(String[] args) throws Exception { Socket s = new Socket("172.22.71.146", 8000); OutputStream os = s.getOutputStream(); byte[] by="ksfsksjfklsdjflsdj".getBytes(); os.write(by); s.close(); } }
动态规划入门到熟悉,看不懂来打我啊
持续更新。。。。。。 2.1斐波那契系列问题 2.2矩阵系列问题 2.3跳跃系列问题 3.1 01背包 3.2 完全背包 3.3多重背包 3.4 一些变形选讲 2.1斐波那契系列问题 在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1, F(n)=F(n-1)+F(n-2)(n&gt;=2,n∈N*)根据定义,前十项为1, 1, 2, 3...
终于明白阿里百度这样的大公司,为什么面试经常拿ThreadLocal考验求职者了
点击上面↑「爱开发」关注我们每晚10点,捕获技术思考和创业资源洞察什么是ThreadLocalThreadLocal是一个本地线程副本变量工具类,各个线程都拥有一份线程私...
对计算机专业来说学历真的重要吗?
我本科学校是渣渣二本,研究生学校是985,现在毕业五年,校招笔试、面试,社招面试参加了两年了,就我个人的经历来说下这个问题。 这篇文章很长,但绝对是精华,相信我,读完以后,你会知道学历不好的解决方案,记得帮我点赞哦。 先说结论,无论赞不赞同,它本质就是这样:对于技术类工作而言,学历五年以内非常重要,但有办法弥补。五年以后,不重要。 目录: 张雪峰讲述的事实 我看到的事实 为什么会这样 ...
Java学习的正确打开方式
在博主认为,对于入门级学习java的最佳学习方法莫过于视频+博客+书籍+总结,前三者博主将淋漓尽致地挥毫于这篇博客文章中,至于总结在于个人,实际上越到后面你会发现学习的最好方式就是阅读参考官方文档其次就是国内的书籍,博客次之,这又是一个层次了,这里暂时不提后面再谈。博主将为各位入门java保驾护航,各位只管冲鸭!!!上天是公平的,只要不辜负时间,时间自然不会辜负你。 何谓学习?博主所理解的学习,它是一个过程,是一个不断累积、不断沉淀、不断总结、善于传达自己的个人见解以及乐于分享的过程。
程序员必须掌握的核心算法有哪些?
由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散的,并没有一本把他们全部覆盖的书籍。下面是我觉得值得学习的一些算法以及数据结构,当然,我也会整理一些看过
大学四年自学走来,这些私藏的实用工具/学习网站我贡献出来了
大学四年,看课本是不可能一直看课本的了,对于学习,特别是自学,善于搜索网上的一些资源来辅助,还是非常有必要的,下面我就把这几年私藏的各种资源,网站贡献出来给你们。主要有:电子书搜索、实用工具、在线视频学习网站、非视频学习网站、软件下载、面试/求职必备网站。 注意:文中提到的所有资源,文末我都给你整理好了,你们只管拿去,如果觉得不错,转发、分享就是最大的支持了。 一、电子书搜索 对于大部分程序员...
Python 植物大战僵尸代码实现(2):植物卡片选择和种植
这篇文章要介绍的是: - 上方植物卡片栏的实现。 - 点击植物卡片,鼠标切换为植物图片。 - 鼠标移动时,判断当前在哪个方格中,并显示半透明的植物作为提示。
防劝退!数据结构和算法难理解?可视化动画带你轻松透彻理解!
大家好,我是 Rocky0429,一个连数据结构和算法都不会的蒟蒻… 学过数据结构和算法的都知道这玩意儿不好学,没学过的经常听到这样的说法还没学就觉得难,其实难吗?真难! 难在哪呢?当年我还是个小蒟蒻,初学数据结构和算法的时候,在忍着枯燥看完定义原理,之后想实现的时候,觉得它们的过程真的是七拐八绕,及其难受。 在简单的链表、栈和队列这些我还能靠着在草稿上写写画画理解过程,但是到了数论、图...
【搞定 Java 并发面试】面试最常问的 Java 并发基础常见面试题总结!
本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star!【Java学习 面试指南】 一份涵盖大部分Java程序员所需要掌握的核心知识。欢迎 Star!)。 另外推荐一篇原创:终极推荐!可能是最适合你的Java学习路线 方法 网站 书籍推荐! Java 并发基础常见面试题总结 1. 什么是线程和进程? 1.1. 何为进程? 进程是程...
西游记团队中如果需要裁掉一个人,会先裁掉谁?
2019年互联网寒冬,大批企业开始裁员,下图是网上流传的一张截图: 裁员不可避免,那如何才能做到不管大环境如何变化,自身不受影响呢? 我们先来看一个有意思的故事,如果西游记取经团队需要裁员一名,会裁掉谁呢,为什么? 西游记团队组成: 1.唐僧 作为团队teamleader,有很坚韧的品性和极高的原则性,不达目的不罢休,遇到任何问题,都没有退缩过,又很得上司支持和赏识(直接得到唐太宗的任命,既给
shell脚本:备份数据库、代码上线
备份MySQL数据库 场景: 一台MySQL服务器,跑着5个数据库,在没有做主从的情况下,需要对这5个库进行备份 需求: 1)每天备份一次,需要备份所有的库 2)把备份数据存放到/data/backup/下 3)备份文件名称格式示例:dbname-2019-11-23.sql 4)需要对1天以前的所有sql文件压缩,格式为gzip 5)本地数据保留1周 6)需要把备份的数据同步到远程备份中心,假如...
iOS Bug 太多,苹果终于坐不住了!
开源的 Android 和闭源的 iOS,作为用户的你,更偏向哪一个呢? 整理 | 屠敏 出品 | CSDN(ID:CSDNnews) 毋庸置疑,当前移动设备操作系统市场中,Android 和 iOS 作为两大阵营,在相互竞争的同时不断演进。不过一直以来,开源的 Android 吸引了无数的手机厂商涌入其中,为其生态带来了百花齐放的盛景,但和神秘且闭源的 iOS 系统相比,不少网友...
神经⽹络可以计算任何函数的可视化证明
《Neural Networks and Deep Learning》读书笔记第四篇本章其实和前面章节的关联性不大,所以大可将本章作为小短文来阅读,当然基本的深度学习基础还是要有的。主要介绍了神经⽹络拥有的⼀种普遍性,比如说不管目标函数是怎样的,神经网络总是能够对任何可能的输入,其值(或者说近似值)是网络的输出,哪怕是多输入和多输出也是如此,我们大可直接得出一个结论:不论我们想要计算什么样的函数,...
聊聊C语言和指针的本质
坐着绿皮车上海到杭州,24块钱,很宽敞,在火车上非正式地聊几句。 很多编程语言都以 “没有指针” 作为自己的优势来宣传,然而,对于C语言,指针却是与生俱来的。 那么,什么是指针,为什么大家都想避开指针。 很简单, 指针就是地址,当一个地址作为一个变量存在时,它就被叫做指针,该变量的类型,自然就是指针类型。 指针的作用就是,给出一个指针,取出该指针指向地址处的值。为了理解本质,我们从计算机模型说起...
为什么你学不过动态规划?告别动态规划,谈谈我的经验
动态规划难吗?说实话,我觉得很难,特别是对于初学者来说,我当时入门动态规划的时候,是看 0-1 背包问题,当时真的是一脸懵逼。后来,我遇到动态规划的题,看的懂答案,但就是自己不会做,不知道怎么下手。就像做递归的题,看的懂答案,但下不了手,关于递归的,我之前也写过一篇套路的文章,如果对递归不大懂的,强烈建议看一看:为什么你学不会递归,告别递归,谈谈我的经验 对于动态规划,春招秋招时好多题都会用到动态...
程序员一般通过什么途径接私活?
二哥,你好,我想知道一般程序猿都如何接私活,我也想接,能告诉我一些方法吗? 上面是一个读者“烦不烦”问我的一个问题。其实不止是“烦不烦”,还有很多读者问过我类似这样的问题。 我接的私活不算多,挣到的钱也没有多少,加起来不到 20W。说实话,这个数目说出来我是有点心虚的,毕竟太少了,大家轻喷。但我想,恰好配得上“一般程序员”这个称号啊。毕竟苍蝇再小也是肉,我也算是有经验的人了。 唾弃接私活、做外...
字节跳动面试官这样问消息队列:分布式事务、重复消费、顺序消费,我整理了一下
你知道的越多,你不知道的越多 点赞再看,养成习惯 GitHub上已经开源 https://github.com/JavaFamily 有一线大厂面试点脑图、个人联系方式和人才交流群,欢迎Star和完善 前言 消息队列在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在消息队列的使用和原理方面对小伙伴们进行360°的刁难。 作为一个在互联网公司面一次拿一次Offer的面霸...
如何安装 IntelliJ IDEA 最新版本——详细教程
IntelliJ IDEA 简称 IDEA,被业界公认为最好的 Java 集成开发工具,尤其在智能代码助手、代码自动提示、代码重构、代码版本管理(Git、SVN、Maven)、单元测试、代码分析等方面有着亮眼的发挥。IDEA 产于捷克,开发人员以严谨著称的东欧程序员为主。IDEA 分为社区版和付费版两个版本。 我呢,一直是 Eclipse 的忠实粉丝,差不多十年的老用户了。很早就接触到了 IDEA...
面试还搞不懂redis,快看看这40道面试题(含答案和思维导图)
Redis 面试题 1、什么是 Redis?. 2、Redis 的数据类型? 3、使用 Redis 有哪些好处? 4、Redis 相比 Memcached 有哪些优势? 5、Memcache 与 Redis 的区别都有哪些? 6、Redis 是单进程单线程的? 7、一个字符串类型的值能存储最大容量是多少? 8、Redis 的持久化机制是什么?各自的优缺点? 9、Redis 常见性...
大学四年自学走来,这些珍藏的「实用工具/学习网站」我全贡献出来了
知乎高赞:文中列举了互联网一线大厂程序员都在用的工具集合,涉及面非常广,小白和老手都可以进来看看,或许有新收获。
为什么要推荐大家学习字节码?
配套视频: 为什么推荐大家学习Java字节码 https://www.bilibili.com/video/av77600176/ 一、背景 本文主要探讨:为什么要学习 JVM 字节码? 可能很多人会觉得没必要,因为平时开发用不到,而且不学这个也没耽误学习。 但是这里分享一点感悟,即人总是根据自己已经掌握的知识和技能来解决问题的。 这里有个悖论,有时候你觉得有些技术没用恰恰是...
互联网公司的裁员,能玩出多少种花样?
裁员,也是一门学问,可谓博大精深!以下,是互联网公司的裁员的多种方法:-正文开始-135岁+不予续签的理由:千禧一代网感更强。95后不予通过试用期的理由:已婚已育员工更有责任心。2通知接下来要过苦日子,让一部分不肯同甘共苦的员工自己走人,以“兄弟”和“非兄弟”来区别员工。3强制996。员工如果平衡不了工作和家庭,可在离婚或离职里二选一。4不布置任何工作,但下班前必须提交千字工作日报。5不给活干+...
【超详细分析】关于三次握手与四次挥手面试官想考我们什么?
在面试中,三次握手和四次挥手可以说是问的最频繁的一个知识点了,我相信大家也都看过很多关于三次握手与四次挥手的文章,今天的这篇文章,重点是围绕着面试,我们应该掌握哪些比较重要的点,哪些是比较被面试官给问到的,我觉得如果你能把我下面列举的一些点都记住、理解,我想就差不多了。 三次握手 当面试官问你为什么需要有三次握手、三次握手的作用、讲讲三次三次握手的时候,我想很多人会这样回答: 首先很多人会先讲下握...
新程序员七宗罪
当我发表这篇文章《为什么每个工程师都应该开始考虑开发中的分析和编程技能呢?》时,我从未想到它会对读者产生如此积极的影响。那些想要开始探索编程和数据科学领域的人向我寻求建议;还有一些人问我下一篇文章的发布日期;还有许多人询问如何顺利过渡到这个职业。我非常鼓励大家继续分享我在这个旅程的经验,学习,成功和失败,以帮助尽可能多的人过渡到一个充满无数好处和机会的职业生涯。亲爱的读者,谢谢你。 -罗伯特。 ...
活到老,学到老,程序员也该如此
全文共2763字,预计学习时长8分钟 图片来源:Pixabay 此前,“网传阿里巴巴要求尽快实现P8全员35周岁以内”的消息闹得沸沸扬扬。虽然很快被阿里辟谣,但苍蝇不叮无缝的蛋,无蜜不招彩蝶蜂。消息从何而来?真相究竟怎样?我们无从而知。我们只知道一个事实:不知从何时开始,程序猿也被划在了“吃青春饭”行业之列。 饱受“996ICU”摧残后,好不容易“头秃了变强了”,即将步入为“高...
Vue快速实现通用表单验证
本文开篇第一句话,想引用鲁迅先生《祝福》里的一句话,那便是:“我真傻,真的,我单单知道后端整天都是CRUD,我没想到前端整天都是Form表单”。这句话要从哪里说起呢?大概要从最近半个月的“全栈工程师”说起。项目上需要做一个城市配载的功能,顾名思义,就是通过框选和拖拽的方式在地图上完成配载。博主选择了前后端分离的方式,在这个过程中发现:首先,只要有依赖jQuery的组件,譬如Kendoui,即使使用...
2019年Spring Boot面试都问了什么?快看看这22道面试题!
Spring Boot 面试题 1、什么是 Spring Boot? 2、Spring Boot 有哪些优点? 3、什么是 JavaConfig? 4、如何重新加载 Spring Boot 上的更改,而无需重新启动服务器? 5、Spring Boot 中的监视器是什么? 6、如何在 Spring Boot 中禁用 Actuator 端点安全性? 7、如何在自定义端口上运行 Sprin...
【图解】记一次手撕算法面试:字节跳动的面试官把我四连击了
字节跳动这家公司,应该是所有秋招的公司中,对算法最重视的一个了,每次面试基本都会让你手撕算法,今天这篇文章就记录下当时被问到的几个算法题,并且每个算法题我都详细着给出了最优解,下面再现当时的面试场景。看完一定让你有所收获 一、小牛试刀:有效括号 大部分情况下,面试官都会问一个不怎么难的问题,不过你千万别太开心,因为这道题往往可以拓展出更多有难度的问题,或者一道题看起来很简单,但是给出最优解,确实很...
关于裁员几点看法及建议
最近网易裁员事件引起广泛关注,昨天网易针对此事,也发了声明,到底谁对谁错,孰是孰非?我们作为吃瓜观众实在是知之甚少,所以不敢妄下定论。身处软件开发这个行业,近一两年来,对...
面试官:关于Java性能优化,你有什么技巧
通过使用一些辅助性工具来找到程序中的瓶颈,然后就可以对瓶颈部分的代码进行优化。 一般有两种方案:即优化代码或更改设计方法。我们一般会选择后者,因为不去调用以下代码要比调用一些优化的代码更能提高程序的性能。而一个设计良好的程序能够精简代码,从而提高性能。 下面将提供一些在JAVA程序的设计和编码中,为了能够提高JAVA程序的性能,而经常采用的一些方法和技巧。 1.对象的生成和大小的调整。 J...
【图解算法面试】记一次面试:说说游戏中的敏感词过滤是如何实现的?
版权声明:本文为苦逼的码农原创。未经同意禁止任何形式转载,特别是那些复制粘贴到别的平台的,否则,必定追究。欢迎大家多多转发,谢谢。 小秋今天去面试了,面试官问了一个与敏感词过滤算法相关的问题,然而小秋对敏感词过滤算法一点也没听说过。于是,有了下下事情的发生… 面试官开怼 面试官:玩过王者荣耀吧?了解过敏感词过滤吗?,例如在游戏里,如果我们发送“你在干嘛?麻痹演员啊你?”,由于“麻痹”是一个敏感词,...
程序员需要了解的硬核知识之汇编语言(一)
之前的系列文章从 CPU 和内存方面简单介绍了一下汇编语言,但是还没有系统的了解一下汇编语言,汇编语言作为第二代计算机语言,会用一些容易理解和记忆的字母,单词来代替一个特定的指令,作为高级编程语言的基础,有必要系统的了解一下汇编语言,那么本篇文章希望大家跟我一起来了解一下汇编语言。 汇编语言和本地代码 我们在之前的文章中探讨过,计算机 CPU 只能运行本地代码(机器语言)程序,用 C 语言等高级语...
GitHub 标星 1.6w+,我发现了一个宝藏项目,作为编程新手有福了!
大家好,我是 Rocky0429,一个最近老在 GitHub 上闲逛的蒟蒻… 特别惭愧的是,虽然我很早就知道 GitHub,但是学会逛 GitHub 的时间特别晚。当时一方面是因为菜,看着这种全是英文的东西难受,不知道该怎么去玩,另一方面是一直在搞 ACM,没有做一些工程类的项目,所以想当然的以为和 GitHub 也没什么关系(当然这种想法是错误的)。 后来自己花了一个星期看完了 Pyt...
相关热词 c# singleton c#中类的默认值是 c#各种进制之间的转换 c# 正则表达式保留汉字 c#后台跨域 c#基础代码大全 c#指定combox选择 c#关系 mono c# 相差毫秒 用c#做一个简易计算器
立即提问