`
1enny
  • 浏览: 70630 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

网络编程

 
阅读更多

java023
网络编程


Socket编程(码头)
socket就是为网络服务提供了一种机制。
通信的两端都有socket
网络通信其实就是socket
数据在两个socket通过IO传输

TCP与UDP
udp:(步话机,QQ)
将数据和源和目的的封装成数据包,不需要建立连接
每个数据报的大小在限制在64k内
因无连接,是不可靠连接
不需要建立连接,速度快

tcp:(下载,打电话)
建立连接,形成传输数据通道
在连接中进行大数据量传输
通过三次握手完成连接,是可靠协议
必须建立连接,效率稍低

udp:示例代码(接收端,发送端)
package NetCoding;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

class SocketSend {

    public static void main(String[] args) throws IOException {
          DatagramSocket socketSend = null;
         DatagramPacket packetSend = null;
          try {
              // 1.建立 udpsocket服务,通过DatagramSocket
             socketSend = new DatagramSocket(8888);
              try {
                  // DatagramPacket(byte[] buf, int length, InetAddress address,
                  // int port)
                 BufferedReader br = new BufferedReader(new InputStreamReader(
                          System. in));
                 String len = "";
                  while ((len = br.readLine()) != null) {
                       if(len.endsWith("over" ))
                           break;
                       byte[] buf = len.getBytes();
                       // 提供数据,并将数据封装到数据包中
                      packetSend = new DatagramPacket(buf, buf.length ,
                              InetAddress. getByName("192.168.1.255"), 10000);//255为广播端口
                       try {
                           // 通过socket服务发送功能,将数据包发送出去
                          socketSend.send(packetSend);
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                 }
             } catch (UnknownHostException e) {
                 e.printStackTrace();
             }

         } catch (SocketException e) {
             System. out.println("创建socket失败" );
         } finally {
              // 关闭资源
             socketSend.close();
         }
    }

}

class SocketReciv {
    @SuppressWarnings( "deprecation")
    public static void main(String args[]) throws UnsupportedEncodingException {
          DatagramSocket socketReci = null;
         DatagramPacket packetReci = null;
          try {
              // 1.创建 udpsocket服务,通常会监听一个端口,其实给这个接收网络应用程序
              // 定义一个数据标识,方便明确哪些数据过来方便与处理
             socketReci = new DatagramSocket(10000);
              byte buf[] = new byte[1024];
              // 2.定义一个数据包,因为要存储接收到的字节数据
              // 因为数据包对象中有更多的功能可以提取字节数据中的不同数据信息
             packetReci = new DatagramPacket(buf, 1024);
              while (true ) {
                  try {
                       // 3. 通过socket服务的receive方法将接收的数据封装到已经定义好的包中
                     socketReci.receive(packetReci); // 阻塞式方法
                       // 通过数据包对象中的特有的功能获取其中的数据
                       byte[] data = packetReci.getData();
                      InetAddress ia = packetReci.getAddress();
                       int port = packetReci.getPort();
                      System. out.println("data="
                               + new String(data, 0, packetReci.getLength(), "gbk" )
                               + "\nhostName=" + ia.getHostName() + "\nhostAddress="
                               + ia.getHostAddress() + "\nport=" + port);
                 } catch (IOException e) {
                      e.printStackTrace();
                 }
             }
         } catch (SocketException e) {
             e.printStackTrace();
         } finally {
             socketReci.close();
         }
    }

}


tcp:示例代码:(客户端,服务端)


package NetCoding;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

/* 客户端对应的对像是socket
 * 服务端对应的对象是socketService
 * 需求:接收服务器回应信息
 * */
/*客户端:
 * 通过查阅socket对象,发现在该对象建立时,就可以去连接指定的主机
 * 因为 tcp是面向连接的,所以建立socket服务时,就要有服务器存在,并且连接成功,形成同路以后,在该通道进行数据的传输
 * 1.建立socket服务,指定要连接的主机和端口
 * 2.获取socket流中的输出流,将数据写到流中。通过网络发送给服务器
 * 3.获取socket流中的输入流,将服务器反馈回来的数据获取到,并打印
 * 4.关闭客户端资源
 * */
class TCPClient {
    public static void main(String[] args) {
          // Socket(String host, int port, InetAddress localAddr, int localPort)
         Socket socket = null;
          try {
             socket = new Socket("localhost" , 10002,
                     InetAddress. getByName("localhost"), 10000);
             OutputStream out = socket.getOutputStream();
             out.write( "服务器 哥们来了...." .getBytes());
             System. out.println( "srvicePortAndAddress:" + socket.getRemoteSocketAddress());
             InputStream in = socket.getInputStream();
              byte[] buf = new byte[1024];
              int len = in.read(buf);//阻塞式
             System. out.println(new String(buf, 0, len));
         } catch (UnknownHostException e) {
             e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
         } finally {
              try {
                 socket.close();
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
    }
}

class TCPService {
    // ServerSocket
    public static void main(String[] args) {
         OutputStream out = null;
         InputStream in = null;
         Socket socket = null;
         ServerSocket serverSocket = null;
          try {
              //建立服务器端socket服务,ServerSocket();并且监听一个端口
             serverSocket = new ServerSocket(10002);
              //获取连接过来的客户端对象,没有连接就会等,所以这个方法阻塞式的
             socket = serverSocket.accept(); //阻塞式
              //客户端如果发送过来数据,那么服务器端要使用对应客户端对象,并且获取该客户端的读取流对象
             System. out.println(socket.getInetAddress());
             
             in = socket.getInputStream();
              byte buf[] = new byte[1024];
              int len = in.read(buf);//阻塞式
             System. out.println(new String(buf, 0,len));
             out = socket.getOutputStream();
             out.write( "客户端,初次见面啊...." .getBytes());
         } catch (IOException e) {
             e.printStackTrace();
         } finally {
              try {
                 out.close();
                 in.close();
                 socket.close();
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
    }
}

package NetCoding;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

class TCPTestClient {

    public static void main(String[] args) {
         Socket socket = null;
         BufferedReader br = null;
         OutputStream out = null;
         InputStream in = null;
         BufferedWriter bw = null;
         BufferedReader brIn = null;
          try {
             socket = new Socket("localhost" , 10000);
             System. out.println("client::::"
                      + socket.getInetAddress().getHostAddress());
             out = socket.getOutputStream();
             bw = new BufferedWriter(new OutputStreamWriter(out));
             br = new BufferedReader(new InputStreamReader(System.in ));
             String len = "";
             in = socket.getInputStream();
             brIn = new BufferedReader(new InputStreamReader(in));
              while ((len = br.readLine()) != null) {
                  if (len.equals("over" ))
                       break;
                 bw.write(len);
                  //在发送数据的最后应该在最后再发送一个换行符,为了在接收方能够判断到了行尾
                 bw.newLine();
                  //数据在缓存中,需要刷新才能发送出去
                 bw.flush();
                 System. out.println(brIn.readLine());
             }

         } catch (Exception e) {
             System. out.println("失败!!" );
         } finally {
              try {
                 in.close();
                 out.close();
                 socket.close(); // 当close时候会像服务器发送-1的结束标志
             } catch (Exception e) {
                 System. out.println("关流失败" );
             }

         }
    }

}

class TCPTestServer {

    public static void main(String[] args) {
         ServerSocket ss = null;
         BufferedReader br = null;
         OutputStream out = null;
         Socket socket = null;
         BufferedWriter bw = null;

          try {
             ss = new ServerSocket(10000);
             socket = ss.accept();
             System. out.println("server::::"
                      + socket.getInetAddress().getHostAddress());
             br = new BufferedReader(new InputStreamReader(
                      socket.getInputStream()));
             String len = null;
             out = socket.getOutputStream();
             bw = new BufferedWriter(new OutputStreamWriter(out));
              while ((len = br.readLine()) != null) {//读到了行尾返回值
                 System. out.println(len);
                 bw.write(len.toUpperCase());
                 bw.newLine();
                 bw.flush();
             }
         } catch (Exception e) {
             System. out.println("获取失败" );
         } finally {
              try {
                 bw.close();
                 out.close();
                 br.close();
                 socket.close();
             } catch (Exception e) {
                 System. out.println("关闭失败" );
             }
         }
    }
}



客户端和服务器端都有阻塞式方法,而这些方法没有读到结束标记,就会一直在等待
操作IO流在读取while循环的时候会出现阻塞情况,特别是读取键盘数据,不确定的数据量。
在此时最好给个结束的标记(读取对方正在写入的输入流时,最好给一个结束标记,有些情况关对方流关闭时会传递-1)

isOutputShutdown()返回是否关闭套接字连接的半写状态 (write-half)。(相当于给输出流传递了一个-1标记)
isInputShutdown()返回是否关闭套接字连接的半读状态 (read-half)。


图片并发的上传:
package NetCoding;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

class PicThreadUploadClient {
    public static void main(String[] args2) {
         BufferedInputStream bis = null;
         BufferedOutputStream bos = null;
         InputStream in = null;
         Socket s = null;
         String args[] = new String[]{"f:\\1.png" };;
          if (args.length == 0) {
             System. out.println("请输入你想上传的图片路径!!" );
              // return;
             
         }
         File f = new File(args[0]);
          if (!f.exists()||!f.isFile()) {
             System. out.println("请输入一个正确的路径" );
              return;
         }
          if (!f.getName().toString().endsWith(".png" )) {
             System. out.println("你传入的必须是图片才行" );
              return;
         }
          if (f.length() > 1024 * 1024 * 4*4) {
             System. out.println("图片太大无法上传!!!" );
              return;
         }

          try {
             s = new Socket("localhost" , 10000);
             bis = new BufferedInputStream(new FileInputStream(f));
             bos = new BufferedOutputStream(s.getOutputStream());
              byte[] buf = new byte[1024];
              int len = 0;
              while ((len = bis.read(buf)) != -1) {
                 bos.write(buf);
                 bos.flush();
             }
             s.shutdownOutput();
             in = s.getInputStream();
             len = in.read(buf);
             System. out.println(new String(buf, 0, len));
         } catch (Exception e) {
             System. out.println("client:::上传失败!!" );
             e.printStackTrace();
         }

    }
}

class PicThreadUploadServer {
    public static void main(String[] args) {

         ServerSocket ss = null;
         Socket s = null;
          try {
             ss = new ServerSocket(10000);
              while (true ) {
                 s = ss.accept();
                  new Thread(new ServerThread(s)).start();
             }
         } catch (Exception e) {
             System. out.println("server::::接收失败" );
         } finally {
              try {
                 ss.close();
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }

    }
}

// 服务器是为多个客户服务的,但是上面的代码明显是只能是为一个用户使用,那怎么样才能多服务呢,
// 其实很简单只要把接收到的请求封装成一个子线程让子线程去为单个客户端服务,所以把服务代码抽取出来
class ServerThread implements Runnable {
    BufferedInputStream bis = null ;
    BufferedOutputStream bos = null ;
    OutputStream out = null ;
    private Socket s;

    public ServerThread(Socket s) {
          this.s = s;
    }

    public void run() {
         String ia = s.getInetAddress().getHostAddress();
          try {
              int count = 1;
             File f = new File("f:\\_" + count + ".jsp");
              while (f.exists() || f.isFile())
                 f = new File("f:\\_" + count++ + ".jsp");

             System. out.println(ia);
             System. out.println(s .getInetAddress());
              bis = new BufferedInputStream(s.getInputStream());
              bos = new BufferedOutputStream(new FileOutputStream(f));
              byte buf[] = new byte[1024];
              int len = 0;
              while ((len = bis .read(buf)) != -1) {
                  bos.write(buf, 0, len);
                  bos.flush();
             }
              out = s .getOutputStream();
              out.write("上传成功!!!" .getBytes());
              out.close();
         } catch (Exception e) {
             System. out.println(ia + "子线程处理出现异常" );
         } finally {
              try {
                  bis.close();
                  bos.close();
             } catch (Exception e) {
                 System. out.println("关流失败!!" );
             }
         }

    }
}


演示:客户端————自定义服务端
doc:telnet(相当于客户端软件) ip 端口 登录远程客户端
package NetCoding;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ModelIE {

    public static void main(String[] args) throws IOException {
         ServerSocket ss = new ServerSocket(10000);
         Socket s = ss.accept();
         InputStream in = s.getInputStream();
         BufferedReader br = new BufferedReader(new InputStreamReader(in));
         String len = null;
          while( (len = br.readLine() )!= null){
             System. out.println(len);
              /*
             GET / HTTP/1.1
Host: localhost:10000
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:29.0) Gecko /20100101 Firefox/29.0
Accept: text/html,application/ xhtml+xml,application/ xml;q=0.9,*/*;q= 0.8
Accept- Language: zh -cn,zh; q=0.8,en- us;q=0.5 ,en;q= 0.3
Accept- Encoding: gzip, deflate
Connection: keep- alive
             
              * */
         }
         s.shutdownInput();
         OutputStream out = s.getOutputStream();
         out.write( "收到你的信息" .getBytes());
    }
}


演示:自定义浏览器————tomcat服务器
package NetCoding;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class ModelIETest {
    
    public static void main(String[] args) throws UnknownHostException,
             IOException {
         Socket s = new Socket( "localhost", 8080);
         InputStream in = s.getInputStream();
         PrintWriter bw = new PrintWriter(s.getOutputStream());
         bw.println( "GET /index.jsp HTTP/1.1");
         bw.println( "Host: localhost:10000");
         bw.println( "User-Agent: Mozilla/5.0 (Windows NT* 6.2; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0 ");
         bw.println( "Accept: */*");
         bw.println( "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
         bw.println( "Connection: keep-alive");
         bw.println();
         bw.println();
         bw.println();
         bw.flush();
         BufferedReader br = new BufferedReader(new InputStreamReader(in));
         String line = "";
          while ((line = br.readLine()) != null) {
             System. out.println(line);
              /*
             HTTP/1.1 200 OK
             Server: Apache-Coyote/1.1
             Content-Type: text/html;charset =ISO-8859-1
             Transfer-Encoding: chunked
             Date: Sat, 24 May 2014 13:56:27 GMT
              * */
         }
    }

}


URL 和 URI(范围更大) URLConnection

package NetCoding;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class URLTest {

    public static void main(String[] args) throws URISyntaxException,
             IOException {
         URL url = new URL(
                  "http://exmail.qq.com/cgi-bin/loginpage?s=session_timeout&from=&r=5b547336e7c8aaa06e3831709242d556" );
         URLConnection urlConnection = url.openConnection();
          // sun.net.www.protocol.http.HttpURLConnection:http://exmail.qq.com/cgi-bin/ loginpage?s=session_timeout&from=&r=5b547336e7c8aaa06e3831709242d556
         System. out.println(urlConnection);
          // http://exmail.qq.com/cgi-bin/loginpage?s=session_timeout&from=&r=5b547336e7c8aaa06e3831709242d556
         System. out.println(url);
          //protected
         HttpURLConnection httpUrlConnection = (HttpURLConnection) url
                 .openConnection();
         Map<String, java.util.List<String>> map = httpUrlConnection.getHeaderFields();
         Set<Entry<String, java.util.List<String>>> en = map.entrySet();
         Iterator<Entry<String, java.util.List<String>>> iterator = en.iterator();
          while(iterator.hasNext()){
             Entry<String, java.util.List<String>> e= iterator.next();
             System. out.println("name=" +e.getKey());
             Iterator<String> i = e.getValue().iterator();
              while(i.hasNext()){
                 System. out.print( "value"+i.hashCode()+"=" +i.next());
             }
         }

    }

    public static void testURL_URI() throws URISyntaxException {
          try {
             URL url = new URL(
                      "http://exmail.qq.com/cgi-bin/loginpage?s=session_timeout&from=&r=5b547336e7c8aaa06e3831709242d556" );
             System. out.println("url:----getProtocol:::" + url.getProtocol());
             System. out.println("url:----getHost:::" + url.getHost());
             System. out.println("url:----getPort:::" + url.getPort());
             System. out.println("url:----getPath:::" + url.getPath());
             System. out.println("url:----getFile:::" + url.getFile());
             System. out.println("url:----getQuery:::" + url.getQuery());
             System. out.println("url:----getAuthority:::" + url.getAuthority());
             System. out.println("url:----url:::" + url);
             URI uri = url.toURI();
             System. out.println("uri:+++++url:::" + uri);
             System. out.println("uri:+++++getHost:::" + uri.getHost());
             System. out.println("uri:+++++getPort:::" + uri.getPort());
             System. out.println("uri:+++++getPath:::" + uri.getPath());
             System. out.println("uri:+++++getRawPath:::" + uri.getRawPath());
             System. out.println("uri:+++++getRawQuery:::" + uri.getRawQuery());
             System. out.println("uri:+++++getAuthority:::" + uri.getAuthority());
             System. out.println("uri:+++++getFragment:::" + uri.getFragment());
         } catch (MalformedURLException e) {
             e.printStackTrace();
         }
          /**
          * url:----getProtocol::: http url:----getHost:::exmail.qq.com
          * url:----getPort::: -1 url:----getPath:::/ cgi- bin/loginpage
          * url:----getFile:::/ cgi- bin/loginpage ?s=session_timeout&from=&r=5
          * b547336e7c8aaa06e3831709242d556
          * url:----getQuery:::s=session_timeout&from
          * = &r=5b547336e7c8aaa06e3831709242d556
          * url:----getAuthority:::exmail.qq.com
          * url:----url :::http://exmail.qq.com
          * / cgi- bin/loginpage ?s=session_timeout
          * &from=&r=5b547336e7c8aaa06e3831709242d556
          * uri:+++++url :::http://exmail
          * .qq.com/cgi- bin/loginpage ?s=session_timeout
          * &from=&r=5b547336e7c8aaa06e3831709242d556
          * uri:+++++getHost:::exmail.qq.com uri:+++++getPort:::-1
          * uri:+++++getPath:::/cgi-bin/loginpage
          * uri:+++++getRawPath:::/cgi-bin/loginpage
          * uri:+++++getRawQuery:::s=session_timeout
          * &from=&r=5b547336e7c8aaa06e3831709242d556
          * uri:+++++getAuthority:::exmail.qq.com uri:+++++getFragment:::null
          */

    }

}


分享到:
评论

相关推荐

    Unix 网络编程 卷1 第三版 源代码

    《UNIX网络编程》(第1卷)(套接口API第3版)第1版和第2版由已故UNIX网络专家W. Richard Stevens博士独自编写。《UNIX网络编程》(第1卷)(套接口API第3版)是3版,由世界著名网络专家Bill Fenner和Andrew M. Rudoff执笔,...

    Linux网络编程 Linux网络编程.TXT

    Linux网络编程 Linux网络编程 Linux网络编程

    网络编程之发送结构体.zip

    网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体...

    网络编程实用教程(程序源代码).zip

    全书分为10章,第1章介绍网络编程的基本概念及模式,第2章介绍套接字网络编程基础,第3章介绍Windows环境的WinSock编程基础,第4章介绍MFC编程,第5章介绍MFC WinSock类的编程,第6章介绍WinInet编程,第7章介绍...

    网络编程合集 TCP-IP详解 windows Linux UNIX Ace 网络编程 7_2

    网络编程合集 TCP-IP详解 windows Linux UNIX Ace 网络编程 搜索关键字:网络编程 TCP-IP详解 windows Linux UNIX 网络编程1_TCP-IP详解卷1.rar 网络编程2_TCP-IP详解卷2-1.rar 网络编程3_windows网络编程电子书及...

    linux C语言 网络编程教程及源码

    linux C语言 网络编程教程及源码 一、网络应用层编程 1、Linux网络编程01——网络协议入门 2、Linux网络编程02——无连接和面向连接的区别 3、Linux网络编程03——字节序和地址转换 4、Linux网络编程04——套接字 5...

    Linux网络编程.pdf

    Linux网络编程

    UNIX网络编程(第1卷)-源码

    《UNIX网络编程 卷1:套接字联网API(第2版)》是一部UNIX网络编程的经典之作。书中全面深入地介绍了如何使用套接字API进行网络编程。全书不但介绍了基本编程内容,还涵盖了与套接字编程相关的高级主题,对于客户/...

    UNIX网络编程_卷2_进程间通信

    《UNIX网络编程.卷2:进程间通信(第2版)》是一部UNIX网络编程的经典之作!进程间通信(IPC)几乎是所有Unix程序性能的关键,理解IPC也是理解如何开发不同主机间网络应用程序的必要条件。《UNIX网络编程.卷2:进程间...

    TCP IP网络编程

    扫描版 超清百度网盘资源!!! 为初学者准备的网络编程! 韩国TCP/IP经典教程!... 本书针对网络编程初学者,面向具备C语言基础的套接字网络编程学习者,适合所有希望学习Linux和Windows网络编程的人。

    C++网络编程文档

    C++网络编程电子书,包括了网络编程的各个方面,内含19个文档。

    C#网络编程技术教程

    《C#网络编程技术教程》注重理论与实践的结合、循序渐进的教学方法。系统介绍了C#网络编程的相关知识,使读者能够快速掌握基于C#的网络应用开发技术。根据应用的需要,《C#网络编程技术教程》在内容安排上对C#基础...

    Linux网络编程

    《Linux网络编程》内容简介:Linux是目前最流行的开源操作系统,网络功能在Linux下占有核心的地位。《Linux网络编程》循序渐进地从应用层到Linux内核、从基本知识点到综合案例,向读者介绍如何在Linux下进行网络程序...

    UNIX网络编程卷1代码.rar

    UNIX网络编程卷1代码.rarUNIX网络编程卷1代码.rar

    ACE网络编程ACE网络编程

    ACE网络编程ACE网络编程;ACE网络编程ACE网络编程;ACE网络编程ACE网络编程

    C#网络编程技术教程\

    C#网络编程技术教程rC#网络编程技术教程

    Java网络编程/Java网络编程实例

    《Java网络编程》,附带《Java网络编程实例》和阅读器,欢迎下载

    网络编程3HTTP编程 网络编程3HTTP编程

    网络编程3HTTP编程 网络编程3HTTP编程 网络编程3HTTP编程

    UNIX网络编程一全套源码

    UNIX网络编程卷一:套接口编程的全套源码!是学习UNIX/LINUX网络编程的经典资料!

    WinSock网络编程经络.pdf

    WinSock网络编程经络 随书源码 本书专门讨论Windows网络编程技术。内容包括NetBIOS和Windows重定向器方法、Winsock方法、客户端远程访问服务器方法。

Global site tag (gtag.js) - Google Analytics