精华内容
下载资源
问答
  • 通用结构体: struct sockaddr { sa_family_t sa_family; /* unsigned short , 指定了通信协议家族 */ char sa_data[14]; };
  • 一个客户端想要发起一次通信,先决条件就是需要知道运行着服务器端程序的主机的IP地址是多少。然后我们才能够通过这个地址向服务器发送信息。
  • Windows 网络编程

    2013-12-19 18:30:17
    本书第一部分讲述的是传统的网络接口N e t B I O S、重定向器以及通过重定向器进行的各类网络通信。尽管本书大部分内容均围绕Wi n s o c k编程这一主题展开,但是, A P I比起Wi n s o c k来,仍然具有某些独到之处...
  • 全书分为10章,第 1章介绍网络编程基础,第 2章介绍套接字网络编程接口,第3章介绍Windows环境的网络编程,第4章介绍MFC编程,第5章介绍MFC WinSock类的编程,第6章介绍WinInet编程,第7章介绍WinSock的多线程编程,...
  • Windows平台上网络编程接口 Windows平台上网络编程接口
  • 《TCP IP网络编程

    热门讨论 2015-06-02 22:23:10
    《TCP/IP网络编程》针对网络编程初学者,面向具备C 语言基础的套接字网络编程学习者,适合所有希望学习Linux和Windows 网络编程的人。 第一部分主要介绍网络编程基础知识。此部分主要论述Windows和Linux平台网络编程...
  • 介绍基于TCP协议通过socket实现网络编程常用API,示例代码:web服务端的编写,实现用户登录及多级页面
  • 本课程包含了socket网络编程常用的所有特性,包括tcp、udp协议的基础编程,广播包,超时连接,多路复用,高并发的epoll多路复用,多线程的服务端。课程讲解理论与实践相结合,实践以代码延时讲解为主。
  • 陈硕 网络编程实战 视频

    热门讨论 2017-04-13 14:37:54
    陈硕于博览网所讲授的网络编程课程 别人录屏而来的 只有某一讲他录错了 其他没有任何问题
  • C++ Socket网络编程

    2016-03-17 10:02:00
    本来搜集到的一些 关于C++ 网络编程 Socket套接字的一些资源
  • linux系统网络编程.pdf

    2019-11-15 14:12:04
    介绍L i n u x系统网络编程的内容,如套接口的概念与使用、网络编程的结构等。简单地说,套接口就是一种使用U N I X系统中的文件描述符和系统进程通信的一种方法。 因为在U N I X系统中,所有的I / O操作都是通过...
  • 1.什么是网络编程? 答:网络编程也叫做socket编程即套接字编程,基于遵循socket套接字的规定进行的编程 2.什么是socket? 答:socket就是一组简单的接口!socket抽象层位于TCP运输层和应用层之间,socket抽象层将...
  • 改资源是zip压缩包,里面包括: UNIX网络编程(第2版)卷1:套接口API和XOpen.传输接口API.pdf UNIX网络编程(第2版)卷2:进程间通信.pdf
  • UNIX网络编程

    2019-03-12 11:26:20
    对于开发网游服务器的人开说,是本非常好的书,书中核心的学习部分还是SOCKET 套接口基本API相关的使用和注意细节,其他部分...网络游戏服务端编程其实针对网络底层所需要的技术点并不多,因此此书只需要针对性的学习。
  • windows网络编程之tcp/ip

    千人学习 2019-01-20 17:33:05
    适用人群 windows网络编程的初学者 课程概述 课程简介: 这部教程是windows网络编程课程的第一部分课程:tcp/ip协议 后续会有第二部分课程:udp/ip协议以及第三部分课程http协议的课程发布。希望能够帮助到大家。 ...
  • Linux的源码里,网络接口的实现部份是非常值得一读的,通过读源码,不仅对网络协议会有更深的了解,也有助于在网络编程的时候,对应用函数有更精确的了解和把握。  本文把重点放在网络接口程序的总体结构上,希望...
  • UNIX网络编程第2版第1卷套接口API和X Open传输接口API 非常牛掰的一本书,希望大家能够从中获得自己想要的知识。
  • 原文链接​ ...可以说是一件令人愉悦的事情,对于用惯了C++网络接口编程的人来说,当他们首次使用Java开发网络应用程序,会发现java开发网络应用是如此的简单,甚至仅用几分钟时间,您就可以学会这种网络编程

    原文链接
    ​http://blog.sina.com.cn/s/blog_616e189f0100rx2i.html​

    第三章:
    java网络编程

             使用java进行网络程序的开发,可以说是一件令人愉悦的事情,对于用惯了C++网络接口编程的人来说,当他们首次使用Java开发网络应用程序,会发现java开发网络应用是如此的简单,甚至仅用几分钟时间,您就可以学会这种网络编程技术。本章主要对java网络编程相关的知识进行探讨,首先探讨java对于网卡信息获取方式,之后介绍如何使用java编写基于网络的客户端和服务端程序。最后探讨一些java网络相关的高级主题。

             3.1 java获取网络通信信息

             java为了方便网络编程,提供了表示IP地址的类、表示网络接口(这个接口是指网卡)的类,表示网络连接接口的类。下面主要探讨这些基本的类,以及如何使用这些类来获取网络信息。Graphic3-1给出了与网络通信信息相关的类之间的关系。

             Graphic3-1 网络通信信息相关的类

    java <wbr>网络编程 <wbr>-- <wbr>IP地址的表示与网络接口信息的获取(InetAddress和NetworkInterface)

     

             3.1.1 InetAddress

             InetAddress用来表示一个IP地址。可以通过主机名来配置InetAddress,此时InetAddress将会通过主机配置的DNS服务器解析出对应域名的IP地址。对于任何的主机名,InetAddress也可以解析出其对应的IP地址。InetAddress拥有两个子类,分别是Inet4AddressInet6Address,在大多说情况下都无需直接处理这些子类,因为InetAddress抽象类已经覆盖了大多数必需的功能。Graphic3-2给出了InetAddress的公有操作。从Graphic3-2从可以看出,InetAddress类没有公有的构造方法,要想获取InetAddress的实例必需使用InetAddress内部的一些静态方法(这是设计模式中的简单工厂方法)。

    Demo3-1给出了使用InetAddress的基本用法。示例中先使用InetAddressgetLocalHost方法获取了本机的IP地址,然后输出,使用getByName方法获得了google服务器的一个IP地址,由于google服务器有很多服务主机,当前获取的是哪一个服务的主机的IP地址并不确定,实际应用中,这是一个随机的值,这与DNS服务器有直接关系。使用了getByAllName方法可以获取google的所有服务主机名。最后使用了isReachable方法来判断一台主机的可达性。

    需要说明的是,使用getLocalHost方法未必真的能够获取您想要的本机的IP地址(有人说,在windowsgetLocalHost可以正确执行,获取到本机的IPV4地址,而在Linux上调用getLocalHost返回的是一个127.0.0.1ip地址)。现在假想有一台主机有多张网卡,而且有多个IP地址,甚至这台主机即配置了IPV4又配置了IPV6,调用getLocalHost将会返回哪一个IP地址?很明显getLocalHost只能返回一个IP地址,因此就限定了getLocalHost方法并不是获取本机IP地址的最好方式。

    Demo3-2给出了一台Linux系统一张网卡上配置IPV4IPV6后,调用getLocalHost后的执行结果。从Configuration3-2中可以看出,在这台linux上配置了IPV4IPV6,调用getLocalHost后,获取的是一个回环测试地址。

    此外,使用InetAddressisReachable时需要特别小心,因为默认情况下,isReachable使用ICMP报文来探测远程主机可达性(不一定使用ICMP,这与具体的实现有关),有很多服务器或者网络管理员禁用ping功能(ICMP),所以使用isReachable不可达,并不证明远程主机不存在。

     

    Graphic3-2  InetAddress拥有的公有操作。

    java <wbr>网络编程 <wbr>-- <wbr>IP地址的表示与网络接口信息的获取(InetAddress和NetworkInterface)

     

    Demo 3-1 InetAddress示例代码

    package com.upc.upcgrid.guan.network.chapter03;

     

    import java.io.IOException;

    import java.net.InetAddress;

     

    public class InetAddressTest {

        public static void main(String[] args) throws IOException {

           InetAddress addr = InetAddress.getLocalHost();//获取本机ip

           System.out.println("local host : "+addr);    

          

           //获取指定服务的一个主机IP

           addr = InetAddress.getByName("google.com");

           System.out.println("google : " + addr);      

          

           //获取指定服务的所有主机IP

           InetAddress[] addrs = InetAddress.getAllByName("google.com");

           for(int i = 0 ;i < addrs.length ;i++)

               System.out.println("google : "+addrs[i] + "  number : " i);     

          

           //获取远程主机可达性

           System.out.println(InetAddress.getByName("localhost").isReachable(1000));   

        }

    }

    Demo3-1执行结果:

    local host : PC2011022509cjh/202.194.158.128

    google : google.com/74.125.71.99

    google : google.com/74.125.71.99  number : 0

    google : google.com/74.125.71.103  number : 1

    google : google.com/74.125.71.104  number : 2

    google : google.com/74.125.71.105  number : 3

    google : google.com/74.125.71.106  number : 4

    google : google.com/74.125.71.147  number : 5

    true

    demo3-1的配置:

    configuration 3-1windows主机的配置

    C:\Documents and Settings\Administrator>ipconfig

    Windows IP Configuration

    Ethernet adapter 本地连接:

            Connection-specific DNS Suffix  . :

            IP Address. . . . . . . . . . . . : 202.194.158.128

            Subnet Mask . . . . . . . . . . . : 255.255.255.0

            Default Gateway . . . . . . . . . : 202.194.158.253

     

    Demo3-2 linux 执行的代码:

           System.out.println(InetAddress.getLocalHost());

    Demo3-2 的输出结果:

    Localhost.localdomain/127.0.0.1

    Demo3-2 的配置环境

    Configuration 3-2 linux主机的配置

    [root@localhost ~]# ifconfig

    eth0      Link encap:Ethernet  HWaddr 00:E0:4C:3D:C2:73 

              inet addr:202.194.158.184  Bcast:202.194.158.255  Mask:255.255.255.0

              inet6 addr: 2001:da8:7006:8003:2e0:4cff:fe3d:c273/64 Scope:Global

              inet6 addr: fe80::2e0:4cff:fe3d:c273/64 Scope:Link

              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

              RX packets:251210956 errors:1 dropped:28 overruns:1 frame:0

              TX packets:116140638 errors:0 dropped:0 overruns:0 carrier:0

              collisions:0 txqueuelen:1000

              RX bytes:16023749113 (14.9 GiB)  TX bytes:34386034544 (32.0 GiB)

              Interrupt:217 Base address:0x2000

     

    lo        Link encap:Local Loopback 

              inet addr:127.0.0.1  Mask:255.0.0.0

              inet6 addr: ::1/128 Scope:Host

              UP LOOPBACK RUNNING  MTU:16436  Metric:1

              RX packets:8274 errors:0 dropped:0 overruns:0 frame:0

              TX packets:8274 errors:0 dropped:0 overruns:0 carrier:0

              collisions:0 txqueuelen:0

              RX bytes:8395613 (8.0 MiB)  TX bytes:8395613 (8.0 MiB)

    3.1.2 NetworkInterface

             可以使用NetworkInterface类提供的方法获取本地计算机网络接口相关的信息。尽管InetAddress类提获取IP地址的方法,但是要想获取本机的网络接口的详细信息,还需要依赖NetworkInterface接口中的方法。通过NetworkInterface接口,可以获取本机配置的网络接口的名字,IP列表(包括IPV4IPV6),网卡地址,最大传输单元(MTU),接口状态(开启/关闭)、接口网络类型(点对点网络、回环网络)等信息。Graphic3-3列出来NetworkInterface中可用的公有方法。从Graphic3-3可以看出,NetworkInterface没有可见的构造方法,NetworkInterface内部也是使用静态方法来构造NetworkInterface实例的(简单工厂方法)。此外,每个NetworkInterface内部可以包含多个NetworkInterface对象,这就构成了一种树结构(合成模式),而且每个NetworkInterface内部保持一个指向父NetworkInterface的引用。

             Demo3-3中给出了一个使用NetworkInterface获取本机eth0网络接口IPV4地址的一个示例程序,首先通过NetworkInterfacegetByName静态方法,获取一个关于eth0NetworkInterface实例,之后调用NetworkInterfacegetInetAddresses获取配置在eth0上的所有IP地址(这时有可能获取到多个IP,因为一个网络接口可以配置多个IP),通过遍历获取的InetAddress,判断如果是IPV4,则将这个IP地址输出出来。需要提示的是,一般每台计算机都会在别名为eth0的网络接口上配置公网的IPV4IPV6的地址,因此,直接使用eth0,即可获取配置的IP地址信息,此外还有一个别名为lo的网络接口,用来进行回环测试,其配置的IPV4一般为127.0.0.1Demo3-3中给出的例子解决了InetAddress调用getLocalHost方法无法正确获取本机IP地址的问题。为了保守起见(防止有的计算机没有为网络端口起名为eth0),demo3-4给出了一个更一般的方法。在Demo3-4中,先通过NetworkInterface的静态方法getNetworkInterfaces获取本机的所有网络接口的父接口,之后遍历这个父接口获取下面的子接口,(在Configuration1Configuration2中都配置了两个子接口,一个名字为eth0,一个名字为lo),之后遍历子接口的IP地址,输出结果。并且在输出中分辨出是IPV4的地址,还是IPV6的地址。

    Graphic3-3 NetworkInterface


    java <wbr>网络编程 <wbr>-- <wbr>IP地址的表示与网络接口信息的获取(InetAddress和NetworkInterface)

     

    Demo3-3 获取本机IPV4的地址

    package com.upc.upcgrid.guan.network.chapter03;

     

    import java.net.InetAddress;

    import java.net.NetworkInterface;

    import java.net.SocketException;

    import java.util.Enumeration;

     

    public class NetworkInterfaceTest {

        public static void main(String[] args) throws SocketException {

           NetworkInterface ni = NetworkInterface.getByName("eth0");

           Enumeration<InetAddress> ias = ni.getInetAddresses();

           for(;ias.hasMoreElements();)

           {

               InetAddress ia = ias.nextElement();

               if(ia instanceof InetAddress)

                  System.out.println(ia);

           }

        }

    }

    Demo3-3的执行结构

    Configuration3-1下:

    /202.194.158.128

    Configuration3-2下:

    /202.194.158.184

    Demo3-4 测试本机的IP地址

    package com.upc.upcgrid.guan.network.chapter03;

     

    import java.net.Inet4Address;

    import java.net.Inet6Address;

    import java.net.InetAddress;

    import java.net.NetworkInterface;

    import java.net.SocketException;

    import java.util.Enumeration;

     

    public class NetworkInterfaceTest2 {

        public static void main(String[] args) throws SocketException {

           Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();

           for(;nis.hasMoreElements();)

           {

               NetworkInterface ni = nis.nextElement();

               Enumeration<InetAddress> ias = ni.getInetAddresses();

               for(;ias.hasMoreElements();)

               {

                  InetAddress ia = ias.nextElement();

                  if(ia instanceof Inet4Address && !ia.getHostAddress().equals("127.0.0.1"))

                  {

                      System.out.println("ip v4 : "+ia);

                  }else if(ia instanceof Inet6Address && !ia.equals(""))

                  {

                      System.out.println("ip v6 : "+ ia);

                  }

               }

              

           }

        }

    }

    Demo3-4的执行结果:

    Configuration3-1 下的执行结果:

    ip v4 : /202.194.158.128

    Configuration3-2下的执行结果:

    ip v6 : /fe80:0:0:0:2e0:4cff:fe3d:c273%2

    ip v6 : /2001:da8:7006:8003:2e0:4cff:fe3d:c273%2

    ip v4 : /202.194.158.184

    ip v6 : /0:0:0:0:0:0:0:1%1

    3.1.3 简单总结

             InetAddress用于表示一个IP地址,其两个子类Inet4AddressInet6Address分别表示IPV4IPV6两种类型的地址。使用InetAddressgetByName方法可以获取远程服务的IP地址(通过DNS服务获取的),使用getAllByName方法可以获取远程指定服务的所有服务主机的IP地址。使用getLocalHost方法可以获取本地IP地址,但是这种方式并不可靠,当出现多张网卡,或一个网络接口配置了多个IP,或者不同的操作系统类型,都不能保证能够获得想要的IP

             NetworkInterface可以获取本机网络接口的相关信息,包括硬件地址,MTU,所有的IP地址等信息,需要获取本机IP时,最好使用NetworkInterface对配置的IP地址进行筛选。

    展开全文
  • Qt中网络编程(网络接口,TCP,UDP)

    万次阅读 2015-12-15 23:41:11
    网络接口信息获取 QNetwork提供QHostInfo类提供的静态函数,进行主机名的查找,使用OS提供的查找机制获取一个与主机名关联的IP地址或者获取一个IP地址关联的主机名 QHostInfo中的静态函数fromName(会阻塞并返回...

    网络接口信息获取

    QNetwork提供QHostInfo类提供的静态函数,进行主机名的查找,使用OS提供的查找机制获取一个与主机名关联的IP地址或者

    获取一个IP地址关联的主机名

    QHostInfo中的静态函数fromName(会阻塞并返回QHostInfo一个对象,这个对象的address函数可以获取其主机的IP地址列表)

    与lookupHost(异步获取,每找到主机就会发送信号)可以进行主机信息的获取


        //QHostInfo 获取主机名查找
        QString localHostName = QHostInfo::localHostName();//获取了本地主机名

    //通过获取主机名 然后两种方式获取其IP地址
    
    
        //fromName 寻找主机信息
        QHostInfo info = QHostInfo::fromName(localHostName);
     
    
        info.addresses();//获取与主机名相关的IP地址列表 包含了ipv4与ipv6

        //lookupHost查找IP地址
        QHostInfo::lookupHost(localHostName, this, SLOT(lookedUp(QHostInfo)));  
    	
    void MainWindow::lookedUp(const QHostInfo &host)  //对应的槽函数
    {
        if (host.error() != QHostInfo::NoError) {  //先判断是否出错
            qDebug() << "Lookup failed:" << host.errorString();
            return;
        }
        foreach (const QHostAddress &address, host.addresses()) //获取地址
            qDebug() << "Found address:" << address.toString();
    }


    Qt网络模块中还提供了QNetworkInterface类获取主机的IP地址列表和网络接口信息。

    QNetworkInterface类代表了运行当前程序的主机的网络接口。

    // 获取所有网络接口的列表
        QList<QNetworkInterface> list = QNetworkInterface::allInterfaces();
        // 遍历每一个网络接口
        foreach (QNetworkInterface interface, list)
        {
            // 接口名称
            qDebug() << "Name: " << interface.name();
            // 硬件地址
            qDebug() << "HardwareAddress: " << interface.hardwareAddress();
            //可以通过它获取所有ip地址
            qDebug()<< "Ip address"<<interface.allAddresses();
     
    
            // 获取IP地址条目列表,每个条目中包含一个IP地址,一个子网掩码和一个广播地址
            QList<QNetworkAddressEntry> entryList = interface.addressEntries();//addressEntries()可以返回一个QNetworkAddressEntry对象的列表
            //QNetworkAddressEntry类保存了一个网络支持的IP 以及该IP地址相关的子网掩码和广播地址
            // 遍历每一个IP地址条目
            foreach (QNetworkAddressEntry entry, entryList)
            {
                // IP地址
                qDebug() << "IP Address: " << entry.ip().toString();
                // 子网掩码
                qDebug() << "Netmask: " << entry.netmask().toString();
                // 广播地址
                qDebug() << "Broadcast: " << entry.broadcast().toString();
            }
        }


    UDP
    Socket"套接字"简单来说:一个IP地址,加一个port端口号。
    其中IP地址指定了网络中的一台主机,而端口号指定了该主机上的一个网络程序,这样使用套接字就可以实现网络上两台主机上的两个应用程序之间的通信。

    UDP(用户数据报协议)是一个轻量级、不可靠、面向数据的、无连接的协议。一般分为发送端与接收端

    发送端
        QUdpSocket *sender;
     
    
        sender = new QUdpSocket(this);
        
        QByteArray datagram = "hello world!";
        sender->writeDatagram(datagram.data(), datagram.size(),QHostAddress::Broadcast, 45454); //广播地址   端口号
        //参数分别为: 数据,数据长度,主机地址,端口号为address的主机的port端口
        //意义是发送size大小的数据包data到地址
        //不建议发送大于512字节的数据报;端口号最好取1024以上的,最大为65535 2的16次方


    接收端
        QUdpSocket *sender;
     
    
        receiver = new QUdpSocket(this);
        receiver->bind(45454, QUdpSocket::ShareAddress);//和发送端端口号一致  不需指定IP。默认支持所有IPV4,绑定模式表明允许其他服务器
        //每当有数据报来时,都会触发readyRead()
        connect(receiver, SIGNAL(readyRead()), this, SLOT(processPendingDatagram()));

    // 处理等待的数据报
    void Receiver::processPendingDatagram()
    {
        // 拥有等待的数据报
        while(receiver->hasPendingDatagrams())    //hasPendingDatagrams()判断是否还有等待的数据报
        {
            QByteArray datagram;
            // 让datagram的大小为等待处理的数据报的大小,这样才能接收到完整的数据
            datagram.resize(receiver->pendingDatagramSize());//pendingDatagramSize() 当前数据包大小
            // 接收数据报,将其存放到datagram中
            receiver->readDatagram(datagram.data(), datagram.size());//readDatagram将不大于指定长度的数据保存到datagram.data()
            ui->label->setText(datagram);
        }
    }


    TCP (HTTP与FTP都是基于TCP的)
    服务器端 如果客户端连接发送信号
    客服端 如果连接上服务器发送信号

    TCP(传输控制协议)用于数据传输的底层网络协议,多个互联网协议(HTTP与FTP都是基于TCP的)。TCP是一个面向数据流和连接的可靠传输协议。TCP传输的是连续的数据流
    TCP编程分为客户端与服务器端,也就是所谓的C/S模型


    TCP编程中

    QTcpSocket中的成员函数

    peerAddress();//获取IP地址 peer指用TCP协议连接在一起的主机的通称

    peerName(); //获取名称

    peerPort();//获取端口号

    read()和write()//进行读写

    bytesAvailable()//度数据之前,确保里面有数据

    关联connect(Socket, SIGNAL(readyRead()), this, SLOT(readMessage())); 当有数据发送过来指定的套接字,便执行槽函数

    发送数据时一定要最开始写入实际数据大小信息(占两个字节) 用quint16表示
    close();套接字的关闭/服务器的关闭

    服务器端

    通过tcpServer->listen(主机IP地址,端口号)绑定主机

    关联connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendMessage()));

    有客服端连接就会发送newConnection()信号,然后在槽函数中通过QTcpSocket *clientConnection = tcpServer-

    >nextPendingConnection();获取与客户端连接的套接字


    关联connect(clientConnection, SIGNAL(disconnected()),clientConnection, SLOT(deleteLater()));//连接断开时 删除套接字

    如果服务器端发送了数据就要进行 套接字的去除

    客户端套接字断开时会发送disconnected(),disconnectFromHost() 函数会一直等待套接字将所有数据发送完毕,然后关闭,

    并发送disconnect信号。

    tcpSocket.waitForDisconnected();//等待知道套接字发送disconnect信号

        QTcpServer *tcpServer;
        tcpServer = new QTcpServer(this);
        // 使用了IPv4的本地主机地址,等价于QHostAddress("127.0.0.1")
        if (!tcpServer->listen(QHostAddress::LocalHost, 6666)) {
            qDebug() << tcpServer->errorString();
            close();
        }
            //每当有客户端连接时,服务器就会发送newConnection()信号
        connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendMessage()));
     
    

    服务器端发送数据
        // 用于暂存我们要发送的数据
        QByteArray block;
     // 获取已经建立的连接的套接字
        QTcpSocket *clientConnection = tcpServer->nextPendingConnection();  //nextPendingConnection()获取连接的套接字
     
    
        connect(clientConnection, SIGNAL(disconnected()),  //连接断开时 删除套接字
                clientConnection, SLOT(deleteLater()));
     
    
        clientConnection->write(block);  
        clientConnection->disconnectFromHost();//disconnectFromHost() 函数会一直等待套接字将所有数据发送完毕,然后关闭,并发送disconnect信号
     客户端 
    

    abort();//取消已有的连接

    通过tcpSocket->connectToHost(主机IP地址,端口号)请求主机

    关联connect(tcpClient, SIGNAL(connected()), this, SLOT(startTransfer()));

    当连接好主机后,主机会发送connected()信号,然后执行槽函数

        QTcpSocket *tcpSocket;
     
    
        tcpSocket = new QTcpSocket(this);
        connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readMessage()));    //当有可读数据发射
        connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),         //当有发生错误
                this, SLOT(displayError(QAbstractSocket::SocketError)));

     
    
        
        // 取消已有的连接
        tcpSocket->abort();
        //调用connectToHost()函数连接到指定主机的指定端口。
        tcpSocket->connectToHost(ui->hostLineEdit->text(),ui->portLineEdit->text().toInt());

    客服端接收数据

    接收数据时一般前两2个字节是整个数据的大小信息   

        // 用来存放数据的大小信息
        quint16 blockSize;
     
        QDataStream in(tcpSocket);
        // 设置数据流版本,这里要和服务器端相同
        in.setVersion(QDataStream::Qt_4_6);
        // 如果是刚开始接收数据
        if (blockSize == 0) {
            //判断接收的数据是否大于两字节,也就是文件的大小信息所占的空间
            //如果是则保存到blockSize变量中,否则直接返回,继续接收数据
            if(tcpSocket->bytesAvailable() < (int)sizeof(quint16)) return;
            in >> blockSize;
        }
        // 如果没有得到全部的数据,则返回,继续接收数据
        if(tcpSocket->bytesAvailable() < blockSize) return;
        // 将接收到的数据存放到变量中
        in >> message;


    获取连接主机的信息
        qDebug() << tcpSocket->peerAddress();//获取IP地址          peer指用TCP协议连接在一起的主机的通称
        qDebug() <<tcpSocket->peerName(); //获取名称
        qDebug() << tcpSocket->peerPort();//获取端口号


    提供简单的代码:完成了网络接口的获取,UDP简单编程,TCP简单编程(服务器发数据,客户端接收)
    展开全文
  • IOS网络编程与云端应用最佳实践,完整扫描版

    千次下载 热门讨论 2014-10-11 21:57:18
    《清华开发者书库:iOS网络编程与云端应用最佳实践》是介绍iOS 6网络编程和云端应用开发技术书籍,介绍了苹果网络、数据交换格式、Web Service、iCloud、定位服务、地图、推送通知、Newsstand、应用内购买、Passbook...
  • Java 网络编程

    万次阅读 多人点赞 2019-05-30 23:07:18
    网络编程 一、网络编程基础概念 首先理清一个概念:网络编程不等于网站编程,网络编程即使用套接字来达到进程间通信,现在一般称为TCP/IP编程。 计算机网络: 把分布在不同地理区域的计算机与专门的外部设备用通信...

    首先理清一个概念:网络编程不等于网站编程,网络编程即使用套接字来达到进程间通信,现在一般称为TCP/IP编程。

    一、计算机网络

    (一)概念

    计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

    (二)计算机网络的主要功能

    1. 资源共享
      资源共享包括计算机硬件资源、软件资源和数据资源的共享。硬件资源的共享提高了计算机硬件资源的利用率,由于受经济和其他因素的制约,这些硬件资派不可能所有用户都有,所以使用计算机网络不仅可以使用自身的硬件资源,也可共享网络上的资源。软件资源和数据资源的共享可以充分利用已有的信息资派.减少软件开发过程中的劳动,避免大型数据库的重复建设。
    2. 信息交换
      这是计算机网络最基本的功能.计算机网络中的计算机之间或计算机与终端之间,可以快速可靠地相互传递数据、程序或文件。例如,用户可以在网上传送电子邮件、交换数据,可以实现在商业部门或公司之间进行订单、发票等商业文件安全准确地交换。
    3. 均衡负荷与分布处理
      对于大型的任务或课题.如果都集中在一台计算机上.负荷太重,这时可以将任务分散到不同的计算机分别完成,或由网络中比较空闲的计算机分担负荷,各个计算机连成网络有利于共同协作进行重大科研课题的开发和研究。利用网络技术还可以将许多小型机或傲型机连成具有高性能的分布式计算机系统,使它具有解决复杂问题的能力,从而大大降低费用。
    4. 综合信息服务
      计算机网络可以向全社会提供各处经济信息、科研情报、商业信息和咨询服务,如Internet中的www就是如此。

    (三)计算机网络分类

    计算机网络按其覆盖的地理范围可分为如下3类:

    • 局域网(LAN)。局域网是一种在小区域内使用的,由多台计算机组成的网络,覆盖范围通常局限在10 千米范围之内,属于一个单位或部门组建的小范围网。
    • 城域网(MAN)。城域网是作用范围在广域网与局域网之间的网络,其网络覆盖范围通常可以延伸到整个城市,借助通信光纤将多个局域网联通公用城市网络形成大型网络,使得不仅局域网内的资源可以共享,局域网之间的资源也可以共享。
    • 广域网(WAN) 广城网是一种远程网,涉及长距离的通信,覆盖范围可以是个国家或多个国家,甚至整个世界。由于广域网地理上的距离可以超过几千千米,所以信息衰减非常严重,这种网络一般要租用专线,通过接口信息处理协议和线路连接起来,构成网状结构,解决寻径问题。

    二、网络通信协议及接口

    (一)网络通信协议

    计算机网络中实现通信必须有一些约定,即通信协议;包括对速率,传输代码,代码结构,传输控制步骤,出错控制等制定的标准。常见的网络通信协议有:TCP/IP协议、IPX/SPX协议、NetBEUI协议等。

    TCP/IP协议:传输控制协议/因特网互联协议(Transmission Control Protocol/Internet Protocal),是Internet最基本、最广泛的协议。它定义了计算机如何连入因特网,以及数据如何在它们之间传输的标准。它的内部包含一系列的用于处理数据通信的协议,并采用了4层的分层模型,每一层都呼叫它的下一层所提供的协议来完成自己的需求。

    (二)网络通信接口

    为了使两个节点之间能进行对话,必须在他们之间建立通信工具(即接口),使彼此之间,能进行信息交换。接口包括两部分:

    • 硬件装置:实现结点之间的信息传送
    • 软件装置:规定双方进行通信的约定协议

    (三)通信协议分层思想

    1.为什么要分层

    由于结点之间联系很复杂,在制定协议时,把复杂成份分解成一些简单的成份,再将它们复合起来。最常用的复合方式就是层次方式,及同层间可以通信,上一层可以调用下一层,而与再下一层不发生关系。各层互不影响,利于系统的开发和扩展。

    2.通信协议的分层规定

    把用户应用程序作为最高层,把物理通信线路作为最底层,将其间的协议处理分为若干层,规定每层处理的任务,也规定每层的接口标准。

    3.参考模型

    在这里插入图片描述
    上图中,TCP/IP协议中的四层分别是应用层、传输层、网络层和链路层,每层分别负责不同的通信功能。

    • 应用层:主要负责应用程序的协议,例如HTTP协议、FTP协议等。
    • 传输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议。
    • 网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络。
    • 数据链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、网线提供的驱动。

    我们编写的程序位于应用层,因此我们的程序是和TCP/UDP打交道的。

    (四)协议分类

    通信的协议还是比较复杂的,java.net包中包含的类和接口,它们提供低层次的通信细节,我们可以直接使用这些类和接口,来专注于网络程序开发,而不用考虑通信的细节。

    java.net包中提供了两种常见的网络协议的支持:TCP和UDP

    • TCP是可靠的连接,TCP就像打电话,需要先打通对方电话,等待对方有回应后才会跟对方继续说话,也就是一定要确认可以发信息以后才会把信息发出去。TCP上传任何东西都是可靠的,只要两台机器上建立起了连接,在本机上发送的数据就一定能传到对方的机器上。
    • UDP就好比发电报,发出去就完事了,对方有没有接收到它都不管,所以UDP是不可靠的。
    • TCP传送数据虽然可靠,但传送得比较慢;UDP传送数据不可靠,但是传送得快。

    1.UDP

    • 用户数据报协议(User Datagram Protocol)。
    • 数据报(Datagram):网络传输的基本单位
    • UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
    • 由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
    • 但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时,不建议使用UDP协议。
    • 特点:数据被限制在64kb以内,超出这个范围就不能发送了。

    2.TCP

    • 传输控制协议(Transmission Control Protocol)。
    • TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。
    • 在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”。

    (1)三次握手

    TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。

    在这里插入图片描述

    • 第一次握手,客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。
      (客户端向服务器端发出连接请求,等待服务器确认。)
    • 第二次握手,服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。(服务器端向客户端回送一个响应,通知客户端收到了连接请求。)
    • 第三次握手,客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。(客户端再次向服务器端发送确认信息,确认连接。)

    三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了。

    (2)四次挥手

    其次,TCP的客户端和服务端断开连接,需要四次挥手
    在这里插入图片描述

    • 客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。
    • 服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSED_WAIT 状态。
    • 客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。
    • 等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。
    • 客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态
    • 服务器收到了 ACK 应答报文后,就进入了 CLOSE 状态,至此服务端已经完成连接的关闭。
    • 客户端在经过 2MSL 一段时间后,自动进入 CLOSE 状态,至此客户端也完成连接的关闭。

    你可以看到,每个方向都需要一个 FIN 和一个 ACK,因此通常被称为四次挥手。这里一点需要注意是:主动关闭连接的,才有 TIME_WAIT 状态。

    为什么挥手需要四次?
    关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。服务器收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK 和 FIN 一般都会分开发送,从而比三次握手导致多了一次。参考

    通俗理解:

    • 三次握手
      A:我要过来了!B:我知道你要过来了!A:我现在过来!
    • 四次挥手
      A:我们分手吧!B:真的分手吗?B:真的真的要分手吗?A:是的!

    由此,可以可靠地进行连接和断开。

    三、IP协议

    (一)概念

    IP协议:网络互连协议

    在这里插入图片描述
    每个人的电脑都有一个独一无二的IP地址,这样互相通信时就不会传错信息了。

    (二)分类

    IP地址根据版本可以分类为:IPv4和IPv6

    IPv4IPv6
    地址长度IPv4协议具有32位(4字节)地址长度IPv6协议具有128位(16字节)地址长度
    格式IPv4 地址的文本格式为 nnn.nnn.nnn.nnn,其中 0<=nnn<=255,而每个 n 都是十进制数。可省略前导零。IPv6 地址的文本格式为 xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx,其中每个 x 都是十六进制数可省略前导零。
    数量共有43亿,30亿在北美,4亿在亚洲,2011年就已经用尽多到每一粒沙子都可以分配一个IPv6地址

    在这里插入图片描述
    IPv4又可以分为五类:

    • A类:在IP地址的四段号码中,第一段号码为网络号码,剩下的三段号码为本地计算机的号码;A类IP地址中网络的标识长度为8位,主机标识的长度为24位,A类网络地址数量较少,有126个网络,每个网络可以容纳主机数达1600多万(256的三次方-2)台。

    • B类:在IP地址的四段号码中,前两段号码为网络号码。B类IP地址中网络的标识长度为16位,主机标识的长度为16位,B类网络地址适用于中等规模的网络,有16384个网络,每个网络所能容纳的计算机数为6万多(256的二次方-2)台

    • C类:在IP地址的四段号码中,前三段号码为网络号码,剩下的一段号码为本地计算机的号码;此类地址中网络的标识长度为24位,主机标识的长度为8位,C类网络地址数量较多,有209万余个网络。适用于小规模的局域网络,每个网络最多只能包含254(256-2)台计算机

    • D类:此类IP地址在历史上被叫做多播地址(multicast address),即组播地址;在以太网中,多播地址命名了一组应该在这个网络中应用接收到一个分组的站点;多播地址的最高位必须是“1110”,范围从224.0.0.0到239.255.255.255

    • E类: 此类地址也不分网络地址和主机地址,它的第1个字节的前五位固定为“11110”,为将来使用保留,地址范围从240.0.0.1到255.255.255.254

    (三)InetAddress类

    说到IP地址,就要引入一个类:InetAddress
    此类表示互联网协议 (IP) 地址
    在这里插入图片描述

    InetAddress类无构造方法

    1.常用方法摘要

    byte[] getAddress()
    返回此 InetAddress 对象的原始 IP 地址。
    static InetAddress getByName(String host)
    在给定主机名的情况下确定主机的 IP 地址。
    String getHostAddress()
    返回 IP 地址字符串(以文本表现形式)。
    String getHostName()
    获取此 IP 地址的主机名。
    static InetAddress getLocalHost()
    返回本地主机。
    127.0.0.1:本机地址,主要用于测试。别名:Localhost

    案例演示1

    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    public class TestIP {
        public static void main(String[] args) throws UnknownHostException {
            //InetAdress类表示IP地址
    
            //获取本机IP
            InetAddress ip = InetAddress.getLocalHost();// ADMINISTRATOR/192.xxx.xxx.xxx
            System.out.println(ip);
            //获得主机名
            System.out.println(ip.getHostName());// ADMINISTRATOR
            //获得IP地址
            System.out.println(ip.getHostAddress());// 192.xxx.xxx.xxx
            //getLocalHost=getHostName+getHostAddress
            System.out.println(InetAddress.getByName("localhost"));
        }
    }
    

    案例演示2

    import java.net.InetAddress;
    import java.net.UnknownHostException;
    
    public class TestIP2 {
        public static void main(String[] args) throws UnknownHostException {
            InetAddress inetAddress = InetAddress.getByName("www.baidu.com");
            // 获取此 IP 地址的主机名。
            System.out.println(inetAddress.getHostName());
            //返回 IP 地址字符串(以文本表现形式)。
            System.out.println(inetAddress.getHostAddress());
        }
    }
    

    在这里插入图片描述

    四、端口

    • IP地址用来标识一台计算机,但是一台计算机上可能提供多种网络应用程序,如何来区分这些不同的程序呢?这就要用到端口。端口号是用来区分一台机器上不同的应用程序的。
    • 我们使用IP地址加端口号,就可以保证数据准确无误地发送到对方计算机的指定软件上了。
    • 端口是虚拟的概念,是一个逻辑端口。
    • 当我们使用网络软件一打开,那么操作系统就会为网络软件分配一个随机的端口号,或者打开的时候向系统要指定的端口号。
    • 通过端口,可以在一个主机上运行多个网络应用程序。端口的表示是一个16位的二进制整数,2个字节,对应十进制的0~65535
    • 端口号在计算机内部是占2个字节。一台机器上最多有65536个端口号。一个应用程序可以占用多个端口号。端口号如果被一个应用程序占用了,那么其他的应用程序就无法再使用这个端口号了。
    • 记住一点,我们编写的程序要占用端口号的话占用1024以上的端口号,1024以下的端口号不要去占用,因为系统有可能会随时征用。端口号本身又分为TCP端口和UDP端口,TCP的8888端口和UDP的8888端口是完全不同的两个端口。TCP端口和UDP端口都有65536个

    (一)分类

    1. 公有端口:0~1023
      • HTTP:80
      • HTTPS:443
      • FTP:21
      • Telnet:23
    2. 程序注册端口(分配给用户或者程序):1024~49151
      • Tomcat:8080
      • MySQL:3306
      • Oracle:1521
    3. 动态、私有端口:49152~65535

    (二)DOS命令查看端口

    • 查看所有端口:netstat -ano
    • 查看指定端口:netstat -ano|findstr "端口号"
    • 查看指定端口的进程:tasklist|findstr "端口号"

    (三)InetSocketAddress类

    说到端口,则要引入一个类:InetSocketAddress

    此类实现 IP 套接字地址(IP 地址 + 端口号)。

    1.构造方法摘要

    InetSocketAddress(InetAddress addr, int port)
    根据 IP 地址和端口号创建套接字地址。
    InetSocketAddress(int port)
    创建套接字地址,其中 IP 地址为通配符地址,端口号为指定值。
    InetSocketAddress(String hostname, int port)
    根据主机名和端口号创建套接字地址。

    2.常用方法摘要

    InetAddress getAddress()
    获取 InetAddress。
    String getHostName()
    获取 hostname。
    int getPort()
    获取端口号。

    案例演示

    import java.net.InetAddress;
    import java.net.InetSocketAddress;
    
    public class TestPort {
        public static void main(String[] args) {
            InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1",8082);
            System.out.println(inetSocketAddress);
            //返回主机名
            System.out.println(inetSocketAddress.getHostName());
            //获得InetSocketAddress的端口
            System.out.println(inetSocketAddress.getPort());
            //返回一个InetAddress对象(IP对象)
            InetAddress address = inetSocketAddress.getAddress();
            System.out.println(address);
        }
    }
    

    在这里插入图片描述

    五、TCP网络编程和UDP网络编程

    网络编程也叫做Socket编程,即套接字编程。套接字指的是两台设备之间通讯的端点。

    在这里插入图片描述

    (一)TCP网络编程

    1.概述

    TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)与服务端(Server)。

    (1)两端通信时步骤:

    1. 服务端程序,需要事先启动,等待客户端的连接。
    2. 客户端主动连接服务器端,连接成功才能通信。服务端不可以主动连接客户端。

    (2)在Java中,提供了两个类用于实现TCP通信程序:

    1. 客户端:java.net.Socket 类表示。创建Socket对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信。
    2. 服务端:java.net.ServerSocket 类表示。创建ServerSocket对象,相当于开启一个服务,并等待客户端的连接。

    2.Socket类

    Socket 类:该类实现客户端套接字,套接字指的是两台设备之间通讯的端点。

    (1)构造方法摘要

    • public Socket(String host, int port) :创建套接字对象并将其连接到指定主机上的指定端口号。如果指定的host是null ,则相当于指定地址为回送地址
      回送地址(127.x.x.x) 是本机回送地址(Loopback Address),主要用于网络软件测试以及本地机进程间通信,无论什么程序,一旦使用回送地址发送数据,立即返回,不进行任何网络传输。

    案例演示

    Socket client = new Socket("127.0.0.1", 6666);
    

    (2)常用方法摘要

    • public InputStream getInputStream() : 返回此套接字的输入流。

      • 如果此Scoket具有相关联的通道,则生成的InputStream 的所有操作也关联该通道。
      • 关闭生成的InputStream也将关闭相关的Socket。
    • public OutputStream getOutputStream() : 返回此套接字的输出流。

      • 如果此Socket具有相关联的通道,则生成的OutputStream 的所有操作也关联该通道。
      • 关闭生成的OutputStream也将关闭相关的Socket。
    • public void close() :关闭此套接字。

      • 一旦一个socket被关闭,它不可再使用。
      • 关闭此socket也将关闭相关的InputStream和OutputStream 。
    • public void shutdownOutput() : 禁用此套接字的输出流。

      • 任何先前写出的数据将被发送,随后终止输出流。

    3.ServerSocket类

    ServerSocket类:这个类实现了服务器套接字,该对象等待通过网络的请求。

    (1)构造方法摘要

    • public ServerSocket(int port) :使用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指定的端口号上,参数port就是端口号。

    案例演示

    ServerSocket server = new ServerSocket(6666);
    

    (2)常用方法摘要

    • public Socket accept() :侦听并接受连接,返回一个新的Socket对象,用于和客户端实现通信。该方法会一直阻塞直到建立连接。

    4.代码实现

    案例演示1

    客户端:

    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.Socket;
    
    public class TCPClient {
        public static void main(String[] args){
            Socket socket = null;
            OutputStream os = null;
            try {
                //1、创建Socket对象,它的第一个参数需要的是服务端的IP,第二个参数是服务端的端口
                InetAddress inet = InetAddress.getByName("127.0.0.1");
                socket = new Socket(inet,8090);
                //2、获取一个输出流,用于写出要发送的数据
                os = socket.getOutputStream();
                //3、写出数据
                os.write("你好,我是客户端!".getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            } finally {//4、释放资源
                if(socket!=null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(os!=null){
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    

    服务端:

    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServer {
        public static void main(String[] args) {
            ServerSocket serverSocket = null;
            Socket socket = null;
            InputStream is = null;
            ByteArrayOutputStream baos = null;
            try {
                //1、创建服务端的ServerSocket,指明自己的端口号
                serverSocket = new ServerSocket(8090);
                //2、调用accept接收到来自于客户端的socket
                socket = serverSocket.accept();//阻塞式监听,会一直等待客户端的接入
                //3、获取socket的输入流
                is = socket.getInputStream();
    
    //        不建议这样写:因为如果我们发送的数据有汉字,用String的方式输出可能会截取汉字,产生乱码
    //        int len=0;
    //        byte[] buffer = new byte[1024];
    //        while ((len=is.read(buffer))!=-1){
    //            String str = new String(buffer, 0, len);
    //            System.out.println(str);
    //        }
                
                //4、读取输入流中的数据
                //ByteArrayOutputStream的好处是它可以根据数据的大小自动扩充
                baos = new ByteArrayOutputStream();
                int len=0;
                byte[] buffer = new byte[1024];
                while ((len=is.read(buffer))!=-1){
                    baos.write(buffer,0,len);
                }
                System.out.println("收到了来自于客户端"+socket.getInetAddress().getHostName()
                        +"的消息:"+baos.toString());
            } catch (IOException e) {
                e.printStackTrace();
            } finally {//5、关闭资源
                if(serverSocket!=null){
                    try {
                        serverSocket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(socket!=null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(is!=null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(baos!=null){
                    try {
                        baos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    

    在这里插入图片描述
    服务器是没有IO流的,服务器可以获取到请求的客户端对象socket
    使用每个客户端socket中提供的IO流和客户端进行交互
    服务器使用客户端的字节输入流读取客户端发送的数据
    服务器使用客户端的字节输出流给客户端回写数据

    案例演示2
    服务端向客户端回写数据

    客户端:

    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.Socket;
    
    public class TCPClient {
        public static void main(String[] args){
            Socket socket = null;
            OutputStream os = null;
            ByteArrayOutputStream baos=null;
            InputStream is=null;
            try {
                //1、创建Socket对象,它的第一个参数需要的是服务端的IP,第二个参数是服务端的端口
                InetAddress inet = InetAddress.getByName("127.0.0.1");
                socket = new Socket(inet,8888);
                //2、获取一个输出流,用于写出要发送的数据
                os = socket.getOutputStream();
                //3、写出数据
                os.write("你好,我是客户端!".getBytes());
                //==========================解析回复==================================
                //4、首先必须通知服务器,我已经输出完毕了,不然服务端不知道什么时候输出完毕
                //服务端的while循环会一直执行,会阻塞
                socket.shutdownOutput();
                ///5、获取输入流,用于读取服务端回复的数据
                is = socket.getInputStream();
                baos = new ByteArrayOutputStream();
                int len=0;
                byte[] buffer = new byte[1024];
                while ((len=is.read(buffer))!=-1){
                    baos.write(buffer,0,len);
                }
                System.out.println("收到了来自服务端的消息:"+baos.toString());
            } catch (IOException e) {
                e.printStackTrace();
            } finally {//6、释放资源
                if(socket!=null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(os!=null){
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(is!=null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (baos!=null){
                    try {
                        baos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    

    服务端:

    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServer {
        public static void main(String[] args) {
            ServerSocket serverSocket = null;
            Socket socket = null;
            InputStream is = null;
            ByteArrayOutputStream baos = null;
            OutputStream os=null;
            try {
                //1、创建服务端的ServerSocket,指明自己的端口号
                serverSocket = new ServerSocket(8888);
                //2、调用accept接收到来自于客户端的socket
                socket = serverSocket.accept();//阻塞式监听,会一直等待客户端接入
                //3、获取socket的输入流
                is = socket.getInputStream();
    
    //        不建议这样写:因为如果我们发送的数据有汉字,用String的方式输出可能会截取汉字,产生乱码
    //        int len=0;
    //        byte[] buffer = new byte[1024];
    //        while ((len=is.read(buffer))!=-1){
    //            String str = new String(buffer, 0, len);
    //            System.out.println(str);
    //        }
    
                //4、读取输入流中的数据
                //ByteArrayOutputStream的好处是它可以根据数据的大小自动扩充
                baos = new ByteArrayOutputStream();
                int len=0;
                byte[] buffer = new byte[1024];
                while ((len=is.read(buffer))!=-1){
                    baos.write(buffer,0,len);
                }
                System.out.println("收到了来自于客户端"+socket.getInetAddress().getHostName()
                        +"的消息:"+baos.toString());
                //===========================回复==========================================
                //5、获取一个输出流,写出回复给客户端
                os = socket.getOutputStream();
                //6、写出数据
                os.write("你好,我是服务端".getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            } finally {//7、关闭资源
                if(serverSocket!=null){
                    try {
                        serverSocket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(socket!=null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(is!=null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(baos!=null){
                    try {
                        baos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(os!=null){
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    

    在这里插入图片描述
    在这里插入图片描述
    案例演示3
    上传文件:客户端发送文件给服务端,服务端将文件保存在本地
    在这里插入图片描述

    客户端:

    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.Socket;
    
    public class TCPClient {
        public static void main(String[] args) {
            Socket socket = null;
            FileInputStream fis = null;
            OutputStream os = null;
            try {
                //1、创建Socket对象,它的第一个参数需要的是服务端的IP,第二个参数是服务端的端口
                InetAddress inet = InetAddress.getByName("127.0.0.1");
                socket = new Socket(inet, 8888);
                //2、创建一个文件输入流,读取要上传的文件
                fis = new FileInputStream("D:/test/touxiang.jpg");
                //3、获取一个输出流,用于写出要发送的数据
                os = socket.getOutputStream();
                byte[] buffer = new byte[1024];
                int len=0;
                while((len=fis.read(buffer))!=-1){
                    //4、写出数据
                    os.write(buffer,0,len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {//5、释放资源
                if(socket!=null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(fis!=null){
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(os!=null){
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    

    服务端:

    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServer {
        public static void main(String[] args) {
            ServerSocket serverSocket = null;
            Socket socket = null;
            FileOutputStream fos = null;
            InputStream is = null;
            try {
                //1、创建服务端的ServerSocket,指明自己的端口号
                serverSocket = new ServerSocket(8888);
                //2、调用accept接收到来自于客户端的socket
                socket = serverSocket.accept();//阻塞式监听,会一直等待客户端的接入
                //3、创建一个文件输出流,用于将读取到的客户端上传的文件输出
                fos = new FileOutputStream("touxiang.jpg");
                //4、获取socket的输入流
                is = socket.getInputStream();
                byte[] buffer = new byte[1024];
                int len=0;
                while((len=is.read(buffer))!=-1){
                    fos.write(buffer,0,len);//5、写出文件
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {//6、释放资源
                if(serverSocket!=null){
                    try {
                        serverSocket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(socket!=null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(fos!=null){
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(is!=null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    

    假设大海里有许多岛屿,客户端和服务端相当于其中的两座岛屿,“客户端”岛屿生产了一种农作物要运到“服务端”岛屿,所以“客户端”要知道“服务端”确切的地址(IP),不然就运错地方了,socket就相当于运输的船只,port就相当于“服务端”岛屿的某个港口。

    (二)UDP网络编程

    从技术意义上来讲,只有TCP才会分Server和Client。对于UDP来说,严格意义上,并没有所谓的Server和Client。
    java.net包给我们提供了两个类DatagramSocket(此类表示用于发送和接收数据报的套接字)和DatagramPacket(该类表示数据报的数据包。 )

    1.DatagramSocket

    (1)构造方法摘要

    protected DatagramSocket()构造数据报套接字并将其绑定到本地主机上的任何可用端口。
    protected DatagramSocket(int port)构造数据报套接字并将其绑定到本地主机上的指定端口。
    protected DatagramSocket(int port, InetAddress laddr)创建一个数据报套接字,绑定到指定的本地地址。

    2.DatagramPacket

    (1)构造方法摘要

    DatagramPacket(byte[] buf, int offset, int length)构造一个 DatagramPacket用于接收指定长度的数据报包到缓冲区中。
    DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)构造用于发送指定长度的数据报包到指定主机的指定端口号上。

    (2)常用方法摘要

    byte[] getData() 返回数据报包中的数据。
    InetAddress getAddress() 返回该数据报发送或接收数据报的计算机的IP地址。
    int getLength() 返回要发送的数据的长度或接收到的数据的长度。

    3.代码实现

    案例演示1
    发送方:

    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    
    public class UDPSender {
        public static void main(String[] args) throws IOException {
            //1、创建一个socket
            DatagramSocket socket = new DatagramSocket();
            InetAddress inet = InetAddress.getLocalHost();
            String msg="你好,很高兴认识你!";
            byte[] buffer = msg.getBytes();
            //2、创建一个包(要发送给谁)
            DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length,inet,9090);
            //3、发送包
            socket.send(packet);
            //4、释放资源
            socket.close();
        }
    }
    

    接收方:

    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    
    public class UDPReceiver {
        public static void main(String[] args) throws IOException {
            //1、创建一个socket,开放端口
            DatagramSocket socket = new DatagramSocket(9090);
            byte[] buffer = new byte[1024];
            //2、创建一个包接收数据
            DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
            //3、接收数据
            socket.receive(packet);//阻塞式接收
            //将数据包转换为字符串输出
            String msg = new String(packet.getData(), 0, packet.getLength());
            System.out.println(msg);
            //4、释放资源
            socket.close();
        }
    }
    

    在这里插入图片描述
    注意
    如果是TCP中先启动客户端会报错:
    在这里插入图片描述
    而如果是UDP中先启动发送方不会报错,但会正常退出。

    案例演示2
    完成在线咨询功能,学生和老师在线一对一交流(多线程

    发送方:

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    
    public class UDPSender implements Runnable{
        //创建一个socket
        DatagramSocket socket=null;
        //创建一个流 用于录入键盘的数据
        BufferedReader bfr=null;
        //发送数据目的地的IP
        private String toIP;
        //发送数据目的地的端口
        private int toPort;
    
        public UDPSender(String toIP, int toPort) {
            this.toIP = toIP;
            this.toPort = toPort;
            try {
                socket=new DatagramSocket();//创建一个socket
            } catch (SocketException e) {
                e.printStackTrace();
            }
            bfr=new BufferedReader(new InputStreamReader(System.in));//从键盘录入数据到流中
        }
    
        @Override
        public void run() {
            while (true){//循环发送数据
                try {
                    String msg = bfr.readLine();//从流中读取数据
                    byte[] buffer = msg.getBytes();
                    InetAddress inet = InetAddress.getByName(toIP);
                    DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length, inet, toPort);
                    socket.send(packet);
                    //如果发送了拜拜,则退出发送
                    if(msg.equals("拜拜")){
                        break;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //释放资源
            if(socket!=null){
                socket.close();
            }
            if (bfr!=null){
                try {
                    bfr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    接收方:

    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.SocketException;
    
    public class UDPReceiver implements Runnable{
        //创建一个socket
        DatagramSocket socket=null;
        //接收方自己所在的端口
        private int fromPort;
        //数据发送者的姓名
        private String msgFrom;
    
        public UDPReceiver(int fromPort,String msgFrom) {
            this.fromPort = fromPort;
            this.msgFrom=msgFrom;
            try {
                socket=new DatagramSocket(fromPort);//创建一个socket
            } catch (SocketException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void run() {
            while(true){//循环接收
                try {
                    byte[] buffer = new byte[1024 * 8];
                    DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
                    socket.receive(packet);
                    String msg = new String(packet.getData(), 0, packet.getLength());
                    System.out.println(msgFrom+":"+msg);
                    if (msg.equals("拜拜")){//如果接收到的数据为拜拜,则退出接收
                        break;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //释放资源
            socket.close();
        }
    }
    

    学生线程:

    public class Student {
        public static void main(String[] args) {
            new Thread(new UDPSender("127.0.0.1",8888)).start();
            new Thread(new UDPReceiver(7777,"老师")).start();
        }
    }
    

    老师线程:

    public class Teacher {
        public static void main(String[] args) {
            new Thread(new UDPSender("127.0.0.1",7777)).start();
            new Thread(new UDPReceiver(8888,"学生")).start();
        }
    }
    

    学生的窗口:
    在这里插入图片描述
    老师的窗口:
    在这里插入图片描述

    六、URL

    (一)概念

    URL(Uniform Resource Locator)统一资源定位符,它表示Internet上某一资源的地址。
    通过URL我们可以访问Internet上的各种网络资源,比如最常见的www,ftp站点。浏览器通过解析给定的URL可以在网络上查找相应的文件或其他资源。

    URI=URL+URN

    • URI:Uniform Resource Identifier ,统一资源标志符。
    • URL:Uniform Resource Locator,统一资源定位符。
    • URN:Uniform Resource Name,统一资源命名。

    网络三大基石:HTML,HTTP,URL

    (二)格式

    URL的基本结构由5部分组成:
    <传输协议>://<主机名>:<端口号>/<文件名>#片段名?参数列表

    • 片段名:即锚点,例如看小说,直接定位到章节
    • 参数列表格式:参数名=参数值&参数名=参数值......

    例如:
    http://localhost:8080/index.jsp#a?username=Tom&password=123456

    (三)URL类

    java.net包下

    1.构造方法摘要

    URL(String spec)根据 String 表示形式创建 URL 对象。
    URL(String protocol, String host, int port, String file) 根据指定协议名、主机名、端口号和文件名创建 URL 对象。
    URL(String protocol, String host, String file) 根据指定的协议名、主机名和文件名创建 URL。

    2.常用方法摘要

    String getProtocol()获取此 URL的协议名称。
    String getHost() 获取此 URL 的主机名。
    int getPort() 获取此 URL 的端口号。
    String getPath() 获取此 URL 的文件路径。
    String getFile()获取此 URL 的文件名。
    String getQuery()获取此 URL的查询部分。
    URLConnection openConnection() 返回一个URLConnection实例,表示与URL引用的远程对象的URL 。

    • URLConnection类中又有一个方法:
      InputStream getInputStream() 返回从此打开的连接读取的输入流。

    案例演示1

    import java.net.MalformedURLException;
    import java.net.URL;
    
    public class Test {
        public static void main(String[] args) throws MalformedURLException {
            URL url = new URL("http://localhost:8080/index.jsp?username=Tom&password=123456");
            System.out.println(url.getProtocol());//获取协议名
            System.out.println(url.getHost());//获取主机名
            System.out.println(url.getPort());//获取端口号
            System.out.println(url.getPath());//获取文件路径
            System.out.println(url.getFile());//获取文件名
            System.out.println(url.getQuery());//获取查询名
        }
    }
    

    在这里插入图片描述
    案例演示2
    URL下载网络资源

    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class Test {
        public static void main(String[] args) throws IOException {
            //下载地址
            URL url = new URL("https://img.t.sinajs.cn/t6/style/images/global_nav/WB_logo.png?id=1404211047727");
            //连接到这个资源 HTTP
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            InputStream is = urlConnection.getInputStream();
            FileOutputStream fos = new FileOutputStream("weibo.jpg");
            byte[] buffer = new byte[1024];
            int len=0;
            while ((len=is.read(buffer))!=-1){
                fos.write(buffer,0,len);
            }
            //释放资源
            urlConnection.disconnect();//断开连接
            is.close();
            fos.close();
        }
    }
    

    小结

    在这里插入图片描述

    展开全文
  • UNIX网络编程 卷1(第三版 英文版).pdf

    热门讨论 2016-04-24 09:57:58
    UNIX网络编程卷1第三版的英文版,带书签,完整pdf。
  • Socket 网络编程

    2019-01-07 18:43:14
    Socket 网络编程 SOCKET实际在计算机中提供了一个通信端口,可以通过这个 端口与任何一个具有SOCKET接口的计算机通信。应用程序在网络上 传输,接收的信息都通过这个SOCKET接口来实现。在应用开发中就 像使用文件...
  • UNIX网络编程卷1:套接字联网API(第3版).pdf
  • C#多线程和Socket网络编程精讲

    千人学习 2019-08-04 20:08:47
    【教学理念】  1、把“需要工作的人”变成“工作需要的人”  2、创设“立足学生、突出项目、强化技术、提高能力”的教学局面。  【课程特色】  1、课程设计循序渐进、讲解细致、通俗易懂、非常...
  • 前几天看到公司一个大神看技术文档,打眼瞟了一下,全是英文的表示直接看看不到。但是大神不一样,人家是硕士哦,英文杠杠的,但是自己心里也想看...java网络编程第四版 java_concurrency_in_practice.pdf Java并发实践
  • 利用TCP/IP协议提供的编程接口———Socket(套接字)可以开发出TCP/IP应用程序。正确的使用WindowsSocket,就可使得不同地址下的进程得以在Windows环境下顺利进行各种网络通信,因此研究WinSock更有意义。而基于TCP/IP...
  • 《unix网络编程》【美】W.Richard Stevens著 清华大学出版社 分上卷(套接口API和X/Open传输接口API)和下卷(进程间通信)
  • UNIX网络编程 第2卷 进程间通信 第1部分 简介和TCP/IP? 第1章 简介 第2章 传输层:TCP、UDP和SCTP 第2部 分基本套接口编程? 第3章 套接口编程简介 第4章 基本TCP套接口编程 第5章 TCP客户/服务器程序例子? ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,868,727
精华内容 747,490
关键字:

网络接口