精华内容
下载资源
问答
  • 计算机网络socket编程实验报告
    2021-07-28 06:28:18

    《计算机网络socket编程实验报告》由会员分享,可在线阅读,更多相关《计算机网络socket编程实验报告(4页珍藏版)》请在人人文库网上搜索。

    1、实课程名称实验项目名称实验时间 (日期及节次)专业年级姓名验计算机科学与技术2011 级陈声晓报计算机网络Socket 通信4.16-4.30第 1 节-第 2 节学生所在学院学号指导教师告计算机学院20111913战扬实验室名称4-513计算机 3 机房分 1 室实验成绩预习情况操作技术实验报告附加:综合 实验 创新能力 综合成绩教师签字黑龙江大学教务处黑龙江大学计算机科学与技术专业、软件工程专业计算机网络课程实验报告学号 20111913 姓名 陈声晓 班级 1 班实验时间4.16-4.30 第 1 节-第 2 节实验名称 Socket 通信实验内容 在一台计算机上实现两个程序的通信一、 。

    2、实验目的掌握 Windows 通信程序的编写,通信原理,实际编写通信程序,本试验是后续 实验的基础。做到在一台计算机上实现两个程序的通信。二、 实验环境Windows xp/7三、 主要设计思想与算法1.服务器创建 socket,并规定通信的端口号(大于 1024),等待客户端的连接。 2.客户端创建 socket,通过端口号连接服务端。3. 客户端向服务端发送接收数据。4. 服务端接收发送数据。3. 通信结束,客户端和服务端关闭 socket。4. Socket 通信流程:四、实验结果(测试用例、实验结果)五、 实验总结计算机网络通信利用 java 语言编写时,用到的技术室 socket 技术。任何一个socket 程序都至少包含客户端程序和服务端程序。通过 IP 地址和端口号,实现了两台计算机之间的链接,然后才可以根据具体需要实现通信 。 运行时先运行服务器程序,不难理解,客户端没有开放,就无法连接。

    更多相关内容
  • 本课程源于天津大学开设的计算机网络,使用JAVA实现了一个简易微信,主要功能包括(局域网聊天,添加好友,群发消息,局域网搜索,注册新用户,修改密码等功能),资源包括源代码,exe文件和文档。大作业得分100分,...
  • 2022年TJU计网socket实验,实现简单的web应用
  • 计算机网络 socket实验

    2009-12-07 09:17:26
    在给定的网络环境中,使用程序设计语言,编写并调试实现基于Socket技术的客户机/服务器模式的应用软件。综合运用Java语言,掌握和利用各种语言工具所提供的Socket技术,在TCP协议之上进行面向连接(或在UDP之上实现...
  • 实 验 报 告 课程名称 计算机网络 实验项目名称 Socket通信 4.16-4.30 实验时间 第 1 节-第 2 节 日期及节次 计算机学院 专业 计算机科学与技术 学生所在学院 年级 2011级 学号 20111913 陈声晓 战扬 姓名 指导教师 ...
  • 实 验 报 告 课程名称 实验项目名称 实验时间日期及节次 专业 计算机网络 Socket通信 4.16-4.30 第 1节-第 2节 计算机科学与技术 学生所在学院 计算机学院 年级 姓名 实验室名称 实验成绩 教师签字 2011级 学号 ...
  • 实 验 报 告 课程名称 计算机网络 实验项目名称 Socket通信 4.16-4.30 实验时间 第 1 节-第 2 节 日期及节次 计算机学院 专业 计算机科学与技术 学生所在学院 年级 2011级 学号 20111913 陈声晓 战扬 姓名 指导教师 ...
  • 计算机网络socket编程

    千次阅读 2017-03-30 15:03:20
    转自:... Linux Socket编程(不限Linux) 2010-12-12 21:58 by 吴秦, 238665 阅读, ...“一切皆Socket!...话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的sock
    转自:http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html

    Linux Socket编程(不限Linux)

    2010-12-12 21:58 by 吴秦, 238665 阅读, 66 评论, 收藏, 编辑

    “一切皆Socket!”

    话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket。

    ——有感于实际编程和开源项目研究。

    我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠socket?那什么是socket?socket的类型有哪些?还有socket的基本函数,这些都是本文想介绍的。本文的主要内容如下:

    • 1、网络中进程之间如何通信?
    • 2、Socket是什么?
    • 3、socket的基本操作
      • 3.1、socket()函数
      • 3.2、bind()函数
      • 3.3、listen()、connect()函数
      • 3.4、accept()函数
      • 3.5、read()、write()函数等
      • 3.6、close()函数
    • 4、socket中TCP的三次握手建立连接详解
    • 5、socket中TCP的四次握手释放连接详解
    • 6、一个例子(实践一下)
    • 7、留下一个问题,欢迎大家回帖回答!!!

    1、网络中进程之间如何通信?

    本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类:

    • 消息传递(管道、FIFO、消息队列)
    • 同步(互斥量、条件变量、读写锁、文件和写记录锁、信号量)
    • 共享内存(匿名的和具名的)
    • 远程过程调用(Solaris门和Sun RPC)

    但这些都不是本文的主题!我们要讨论的是网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的。其实TCP/IP协议族已经帮我们解决了这个问题,网络层的“ip地址可以唯一标识网络中的主机,而传输层的“协议+端口可以唯一标识主机中的应用程序(进程)。这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。

    使用TCP/IP协议的应用程序通常采用应用编程接口:UNIX  BSD的套接字(socket)和UNIX System V的TLI(已经被淘汰),来实现网络进程之间的通信。就目前而言,几乎所有的应用程序都是采用socket,而现在又是网络时代,网络中进程通信是无处不在,这就是我为什么说“一切皆socket”。

    2、什么是Socket?

    上面我们已经知道网络中的进程是通过socket来通信的,那什么是socket呢?socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭),这些函数我们在后面进行介绍。

    socket一词的起源

    在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的,撰写者为Stephen Carr、Steve Crocker和Vint Cerf。根据美国计算机历史博物馆的记载,Croker写道:“命名空间的元素都可称为套接字接口。一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定。”计算机历史博物馆补充道:“这比BSD的套接字接口定义早了大约12年。”

    3、socket的基本操作

    既然socket是“open—write/read—close”模式的一种实现,那么socket就提供了这些操作对应的函数接口。下面以TCP为例,介绍几个基本的socket接口函数。

    3.1、socket()函数

    int socket(int domain, int type, int protocol);

    socket函数对应于普通文件的打开操作。普通文件的打开操作返回一个文件描述字,而socket()用于创建一个socket描述符(socket descriptor),它唯一标识一个socket。这个socket描述字跟文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。

    正如可以给fopen的传入不同参数值,以打开不同的文件。创建socket的时候,也可以指定不同的参数创建不同的socket描述符,socket函数的三个参数分别为:

    • domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INETAF_INET6AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
    • type:指定socket类型。常用的socket类型有,SOCK_STREAMSOCK_DGRAMSOCK_RAWSOCK_PACKETSOCK_SEQPACKET等等(socket的类型有哪些?)。
    • protocol:故名思意,就是指定协议。常用的协议有,IPPROTO_TCPIPPTOTO_UDPIPPROTO_SCTPIPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议(这个协议我将会单独开篇讨论!)。

    注意:并不是上面的type和protocol可以随意组合的,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。

    当我们调用socket创建一个socket时,返回的socket描述字它存在于协议族(address family,AF_XXX)空间中,但没有一个具体的地址。如果想要给它赋值一个地址,就必须调用bind()函数,否则就当调用connect()listen()时系统会自动随机分配一个端口。

    3.2、bind()函数

    正如上面所说bind()函数把一个地址族中的特定地址赋给socket。例如对应AF_INETAF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。

    int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    函数的三个参数分别为:

    • sockfd:即socket描述字,它是通过socket()函数创建了,唯一标识一个socket。bind()函数就是将给这个描述字绑定一个名字。
    • addr:一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同,如ipv4对应的是:
      struct sockaddr_in {
          sa_family_t    sin_family; /* address family: AF_INET */
          in_port_t      sin_port;   /* port in network byte order */
          struct in_addr sin_addr;   /* internet address */
      };
      
      /* Internet address. */
      struct in_addr {
          uint32_t       s_addr;     /* address in network byte order */
      };
      ipv6对应的是:
      struct sockaddr_in6 { 
          sa_family_t     sin6_family;   /* AF_INET6 */ 
          in_port_t       sin6_port;     /* port number */ 
          uint32_t        sin6_flowinfo; /* IPv6 flow information */ 
          struct in6_addr sin6_addr;     /* IPv6 address */ 
          uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */ 
      };
      
      struct in6_addr { 
          unsigned char   s6_addr[16];   /* IPv6 address */ 
      };
      Unix域对应的是:
      #define UNIX_PATH_MAX    108
      
      struct sockaddr_un { 
          sa_family_t sun_family;               /* AF_UNIX */ 
          char        sun_path[UNIX_PATH_MAX];  /* pathname */ 
      };
    • addrlen:对应的是地址的长度。

    通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。

    网络字节序与主机字节序

    主机字节序就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。引用标准的Big-Endian和Little-Endian的定义如下:

      a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

      b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

    网络字节序:4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序。由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。字节序,顾名思义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序,一个字节的数据没有顺序的问题了。

    所以:在将一个地址绑定到socket的时候,请先将主机字节序转换成为网络字节序,而不要假定主机字节序跟网络字节序一样使用的是Big-Endian。由于这个问题曾引发过血案!公司项目代码中由于存在这个问题,导致了很多莫名其妙的问题,所以请谨记对主机字节序不要做任何假定,务必将其转化为网络字节序再赋给socket。

    3.3、listen()、connect()函数

    如果作为一个服务器,在调用socket()bind()之后就会调用listen()来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求。

    int listen(int sockfd, int backlog);
    int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数。socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。

    connect函数的第一个参数即为客户端的socket描述字,第二参数为服务器的socket地址,第三个参数为socket地址的长度。客户端通过调用connect函数来建立与TCP服务器的连接。

    3.4、accept()函数

    TCP服务器端依次调用socket()bind()listen()之后,就会监听指定的socket地址了。TCP客户端依次调用socket()connect()之后就想TCP服务器发送了一个连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数取接收请求,这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作。

    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

    accept函数的第一个参数为服务器的socket描述字,第二个参数为指向struct sockaddr *的指针,用于返回客户端的协议地址,第三个参数为协议地址的长度。如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与返回客户的TCP连接。

    注意:accept的第一个参数为服务器的socket描述字,是服务器开始调用socket()函数生成的,称为监听socket描述字;而accept函数返回的是已连接的socket描述字。一个服务器通常通常仅仅只创建一个监听socket描述字,它在该服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字,当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭。

    3.5、read()、write()等函数

    万事具备只欠东风,至此服务器与客户已经建立好连接了。可以调用网络I/O进行读写操作了,即实现了网咯中不同进程之间的通信!网络I/O操作有下面几组:

    • read()/write()
    • recv()/send()
    • readv()/writev()
    • recvmsg()/sendmsg()
    • recvfrom()/sendto()

    我推荐使用recvmsg()/sendmsg()函数,这两个函数是最通用的I/O函数,实际上可以把上面的其它函数都替换成这两个函数。它们的声明如下:

           #include <unistd.h>
    
           ssize_t read(int fd, void *buf, size_t count);
           ssize_t write(int fd, const void *buf, size_t count);
    
           #include <sys/types.h>
           #include <sys/socket.h>
    
           ssize_t send(int sockfd, const void *buf, size_t len, int flags);
           ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    
           ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                          const struct sockaddr *dest_addr, socklen_t addrlen);
           ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                            struct sockaddr *src_addr, socklen_t *addrlen);
    
           ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
           ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
    

    read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0表示已经读到文件的结束了,小于0表示出现了错误。如果错误为EINTR说明读是由中断引起的,如果是ECONNREST表示网络连接出了问题。

    write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数。失败时返回-1,并设置errno变量。 在网络程序中,当我们向套接字文件描述符写时有俩种可能。1)write的返回值大于0,表示写了部分或者是全部的数据。2)返回的值小于0,此时出现了错误。我们要根据错误类型来处理。如果错误为EINTR表示在写的时候出现了中断错误。如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接)。

    其它的我就不一一介绍这几对I/O函数了,具体参见man文档或者baidu、Google,下面的例子中将使用到send/recv。

    3.6、close()函数

    在服务器与客户端建立连接之后,会进行一些读写操作,完成了读写操作就要关闭相应的socket描述字,好比操作完打开的文件要调用fclose关闭打开的文件。

    #include <unistd.h>
    int close(int fd);

    close一个TCP socket的缺省行为时把该socket标记为以关闭,然后立即返回到调用进程。该描述字不能再由调用进程使用,也就是说不能再作为read或write的第一个参数。

    注意:close操作只是使相应socket描述字的引用计数-1,只有当引用计数为0的时候,才会触发TCP客户端向服务器发送终止连接请求。

    4、socket中TCP的三次握手建立连接详解

    我们知道tcp建立连接要进行“三次握手”,即交换三个分组。大致流程如下:

    • 客户端向服务器发送一个SYN J
    • 服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1
    • 客户端再想服务器发一个确认ACK K+1

    只有就完了三次握手,但是这个三次握手发生在socket的那几个函数中呢?请看下图:

    image

    图1、socket中发送的TCP三次握手

    从图中可以看出,当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。

    总结:客户端的connect在三次握手的第二个次返回,而服务器端的accept在三次握手的第三次返回。

    5、socket中TCP的四次握手释放连接详解

    上面介绍了socket中TCP的三次握手建立过程,及其涉及的socket函数。现在我们介绍socket中的四次握手释放连接的过程,请看下图:

    image

    图2、socket中发送的TCP四次握手

    图示过程如下:

    • 某个应用进程首先调用 close主动关闭连接,这时TCP发送一个FIN M;
    • 另一端接收到FIN M之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据;
    • 一段时间之后,接收到文件结束符的应用进程调用 close关闭它的socket。这导致它的TCP也发送一个FIN N;
    • 接收到这个FIN的源发送端TCP对它进行确认。

    这样每个方向上都有一个FIN和ACK。

    6、一个例子(实践一下)

    说了这么多了,动手实践一下。下面编写一个简单的服务器、客户端(使用TCP)——服务器端一直监听本机的6666号端口,如果收到连接请求,将接收请求并接收客户端发来的消息;客户端与服务器端建立连接并发送一条消息。

    服务器端代码:

    服务器端
            
    展开全文
  • 计算机网络 socket编程实现服务器端与客户端连接 服务器端 #include <stdio.h> #include <stdlib.h> #include <winsock2.h> int main() { WSADATA wsaData; WSAStartup(MAKEWORD(2,2),&...

    计算机网络 socket编程实现服务器端与客户端连接

    服务器端

    #include <stdio.h>
    #include <stdlib.h>
    #include <winsock2.h>
    
    int main()
    {
        WSADATA wsaData;
        WSAStartup(MAKEWORD(2,2),&wsaData);
        if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2)
        {
            printf("fail");
            return -1;
        }
    
        SOCKET serverSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
        SOCKADDR_IN serverAddr;     //声明一个SOCKADDR_IN变量,表示服务器
        serverAddr.sin_family = AF_INET;  //必须和创建socket的IP协议一致
        serverAddr.sin_port=htons(8888);  // //服务器端口,客户端通过这个端口连接
        serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); //ip用宏INADDR_ANY代替,代表0.0.0.0,表明所有地址
    
       if(SOCKET_ERROR == bind(serverSocket , (SOCKADDR*)&serverAddr , sizeof(serverAddr))) //绑定
        {
            printf("绑定失败\n");
            closesocket(serverSocket);  //释放socket
            WSACleanup();  //关闭套接字
            return -1;
    	}
    
         printf("绑定成功\n");
    
        listen(serverSocket, 10);//置socket为被动方式
        //等待客户连接
        SOCKADDR_IN clientAddr;
        int len = sizeof(clientAddr);
    
        //接受连接
        SOCKET clientSocket = accept(serverSocket,(SOCKADDR*)&clientAddr, &len);    //阻塞函数
        if(clientSocket == INVALID_SOCKET)
        {
          printf("连接失败");
         closesocket(serverSocket);    //释放socket
         WSACleanup();   //关闭套接字
          return -1 ;
        }
        printf("连接成功\n");
        printf("客户端地址为: %s\n" , inet_ntoa(clientAddr.sin_addr));
    
        char recvBuff[128] = {};
        //开始通讯
        while(1)
        {
          memset(recvBuff, 0 , sizeof(recvBuff));  //初始化recvBuff
          if(recv(clientSocket , recvBuff, sizeof(recvBuff)-1 , 0) >0)  //阻塞函数
          {
               printf("我是服务器,我收到客户端的信息为:  %s\n" , recvBuff);
          }
          else printf("我是服务器,未收到客户端信息");
    
          if(strcmp(recvBuff,"exit")==0) break; //客户端发送exit时,结束通信
    
          char sendBuff[128] = {};
          memset(sendBuff, 0 , sizeof(sendBuff)); //初始化sendBuff
          printf("\n服务器准备向客户端发送信息......\n");
          printf("请输入要发送的信息:\n");
          scanf("%s" , sendBuff);
          if(strcmp(sendBuff,"exit")==0) break; //服务器发送exit时结束通信
          //一次收发
          send(clientSocket , sendBuff, strlen(sendBuff), 0);
        }
        //关闭socket
        closesocket(clientSocket);
        closesocket(serverSocket);
        WSACleanup();
        return 0;
    }
    
    

    客户端

    #include <stdio.h>
    #include <stdlib.h>
    #include <winsock2.h>
    int main()
    {
        WSADATA wsaData;
        WSAStartup(MAKEWORD(2,2),&wsaData);
        if(LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2)
        {
          printf("请求版本失败");
          return -1;
        }
    
        SOCKET clientSocket= socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
        if(INVALID_SOCKET == clientSocket)
        {
           printf("套接字创建失败");
           return -1;
         }
        SOCKADDR_IN clientAddr; //初始化协议地址
        clientAddr.sin_family = AF_INET;//必须和创建socket的IP协议一致
        clientAddr.sin_port = htons(8888);    //服务器端口,客户端通过这个端口连接
    
        //ip地址是点分格式的字符串 , 用inet_addr来转换整数
        clientAddr.sin_addr.S_un.S_addr =inet_addr("127.0.0.1");
     if( connect(clientSocket , (SOCKADDR *)&clientAddr , sizeof(clientAddr))<0)
        {
          printf("连接失败");
          closesocket(clientSocket);    //释放socket
          WSACleanup();   //关闭套接字
          return -1 ;
        }
        printf("连接成功\n\n");
        char sendBuff[128] = {};
        //开始通讯
        while(1)
        {
          memset(sendBuff, 0 , sizeof(sendBuff)); //初始化sendBuff
          printf("请输入客户端向服务器发送的信息:\n");
          scanf("%s" , sendBuff);
          //一次收发
          send(clientSocket , sendBuff, strlen(sendBuff), 0);
    
          char recvBuff[128] = {};
          memset(recvBuff, 0 , sizeof(recvBuff)); //初始化recvBuff
          if(recv(clientSocket , recvBuff, sizeof(recvBuff)-1 , 0) >0)  //阻塞函数
          {
               printf("我是客户端,收到的服务器信息为:%s\n" , recvBuff);
          }
          else printf("客户端未收到服务器信息");
        }
        return 0;
    }
    
    

    使用cmd运行即可

    展开全文
  • 华中科技大学 计算机网络 实验报告 三次 socket tcp cpt组网华中科技大学 计算机网络 实验报告 三次 socket tcp cpt组网华中科技大学 计算机网络 实验报告 三次 socket tcp cpt组网华中科技大学 计算机网络 实验报告...
  • 计算机网络socket编程实验,包括TCP和UDP两种连接方式
  • 计算机网络Socket编程

    2008-06-06 11:18:50
    服务器和客户端的Socket 编程
  • 一个自己写的基于C# SOCKET网络抓包程序,用于监控一段时间局域网IP报文。代码较简单,适合初学者学习和理解SOCKET抓包,希望对大家有用。
  • 计算机网络(四)Socket

    千次阅读 2022-03-01 21:26:27
    介绍了什么是socket,在Windows环境下的socket API,以及在传输层协议为TCP和UDP时使用socket的通信流程。

    目录

    何为socket

    使用socket

    一、C/C++ socket API

    1. 创建socket

    2. 建立连接(仅限TCP)

    3. 通信

    4. 关闭socket

    5. 服务器端完整示例

     5. 客户端完整示例

    二、Socket的通信流程

    1. TCP使用socket的通信流程

    2. UDP使用socket的通信流程


    何为socket

            Socket本身也是进程间通信方式的一种。但是与其他的方式不同,socket可以用于不同主机间的进程通信,这得益于它的创建方式和工作流程。在之前介绍TCP和UDP的文章中,端口作为首部中的一部分被提及,但并未进行详细的描述。实际上端口代表的就是一个进程,而一些特定的进程都有其固定的端口号,如DNS使用的默认端口号为53、通过HTTP向Web服务器请求网页的默认端口号为80等。而套接字的作用就是将端口与进程绑定,从而使发往指定端口的数据能够正确的被相应的进程接收。因此socket的本质就是传输层对应用层提供的接口,通常服务器端与客户端所使用的socket是不同的。在使用TCP时,服务器端会一直存在一个用于监听是否有客户端发起新的连接的socket,这种socket被称之为master socket;当确认需要建立连接时,双方便会各自新建一个用于传输数据的socket,这种socket则被称之为connected socket。在使用UDP时,不会建立真实的连接,而只是在收发数据时指定相应的地址和端口。

    使用socket

            在进程使用socket进行各种操作时,就需要用到其暴露给应用层的各种接口,即socket API。在不同操作系统环境下使用不同语言操作socket的方法都各有不同,在这里主要介绍使用C/C++时的socket API。而通过TCP和UDP进行通信时,使用socket的流程也是不一样的。

    一、C/C++ socket API

            在Linux和Windows环境下,使用socket时需要引入的头文件各不相同,使用的流程、API、数据类型和一些结构体的结构也有所不同,在具体使用时需要深入了解,这里只讨论在Windows环境下对Windows Socket 2的使用。在使用之前,需要在引入相关的静态库 (Ws2_32.lib,或是动态载入Ws2_32.ddl) 后再引入头文件winsock2.h。在操作socket之前,需要调用其中的WSAStartUp() 进行初始化,而在使用完Windows Socket 2之后,需要调用WSACleanup()进行收尾。想要了解更多Windows Socket 2中API的具体使用方法可以阅读官方文档,以下部分仅节选了几个常用的API进行简单的描述:

    1. 创建socket

    /*
        方法
    */
    
    // 创建socket
    SOCKET WSAAPI socket(
      [in] int af,                          // address family,指定地址簇的枚举
      [in] int type,                        // 指定socket类型的枚举
      [in] int protocol                     // 指定使用协议的枚举
    );                                      // 若成功则返回描述符,否则返回INVALID_SOCKET
    
    // 绑定 (无强制规定但通常只有客户端使用)
    // 由于服务器端的进程通常使用固定端口,因此通常必须绑定
    // 由于客户端的进程通常使用随机端口,因此通常不会绑定,否则需要确认当前端口是否已被占用
    int WSAAPI bind(
      [in] SOCKET         s,                // 未绑定socket的描述符
      [in] const sockaddr *name,            // sockaddr结构体的位置,对不同地址簇其含义不同
      [in] int            namelen           // sockaddr结构体的长度
    );                                      // 若成功则返回0,否则返回SOCKET_ERROR
    
    
    /*
        简单示例
    */
    
    // 声明变量
    SOCKET sock;                            // 声明一个socket
    struct sockaddr_in saServer;            // 声明一个sockaddr_in结构体
    hostent* localHost;                     // 声明一个指向本地主机的指针
    char* localIP;                          // 声明一个指向本地主机IP地址的指针
    
    // 创建一个在TCP中使用IPv4地址簇的socket
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    // 获取本地主机信息
    localHost = gethostbyname("");
    localIP = inet_ntoa (*(struct in_addr *)*localHost->h_addr_list);
    
    // 更新sockaddr_in结构体
    saServer.sin_family = AF_INET;
    saServer.sin_addr.s_addr = inet_addr(localIP);
    saServer.sin_port = htons(5150);
    
    // 使用sockaddr_in结构体中的内容绑定socket
    // 传参时将sockaddr_in结构体类型转换成sockaddr结构体
    bind(sock, (SOCKADDR*) & saServer, sizeof (saServer));

    2. 建立连接(仅限TCP)

    /*
        方法
    */
    
    // 监听 (服务器端)
    int WSAAPI listen(
      [in] SOCKET s,                        // 已绑定但未连接的socket的描述符
      [in] int    backlog                   // 挂起连接的队列的最大长度
    );                                      // 若成功则返回0,否则返回SOCKET_ERROR
    
    // 同意连接 (服务器端)
    SOCKET WSAAPI accept(
      [in]      SOCKET   s,                 // 已开启监听的socket的描述符
      [out]     sockaddr *addr,             // 保存客户端信息的sockaddr结构体的位置,可选
      [in, out] int      *addrlen           // sockaddr结构体的长度,可选
    );                                      // 若成功则返回一个已连接的新socket的描述符,
                                            // 否则返回INVALID_SOCKET
    
    // 建立连接 (客户端)
    int WSAAPI connect(
      [in] SOCKET         s,                // 已绑定但未连接的socket的描述符
      [in] const sockaddr *name,            // 包含服务器端信息的sockaddr结构体的位置
      [in] int            namelen           // sockaddr结构体的长度
    );                                      // 若成功则返回0,否则返回SOCKET_ERROR
    
    
    /*
        简单示例
    */
    
    /* 服务器端 */
    
    // 声明变量
    SOCKET AcceptSocket;                    // 声明一个接受连接的socket
    
    // 开始监听
    // SOMAXCONN会将队列的最大长度置为最大的合理值
    listen(sock, SOMAXCONN)
    
    // 同意连接
    // NULL表示不保存客户端信息
    // 会阻塞进程直到收到客户端发起的连接
    AcceptSocket = accept(sock, NULL, NULL);
    
    /* 客户端 */
    
    // 声明变量
    struct sockaddr_in clientService;       // 声明一个sockaddr_in结构体
    
    // 将服务器端的信息更新到sockaddr_in结构体中
    clientService.sin_family = AF_INET;
    clientService.sin_addr.s_addr = inet_addr("127.0.0.1");
    clientService.sin_port = htons(27015);
    
    // 连接到指定的服务器端socket
    // 传参时将sockaddr_in结构体类型转换成sockaddr结构体
    connect(sock, (SOCKADDR *) & clientService, sizeof (clientService));

    3. 通信

    /*
        方法
    */
    
    // 发送 (需要连接)
    int WSAAPI send(
      [in] SOCKET     s,                    // 发送端socket的描述符
      [in] const char *buf,                 // 存有准备发送数据的缓存位置
      [in] int        len,                  // 要发送数据的字节数
      [in] int        flags                 // 指定调用方式的标志,用按位或运算得出,通常为0
    );                                      // 若成功则返回实际发送的字节数,
                                            // 否则返回SOCKET_ERROR
    
    // 接收 (需要连接)
    int WSAAPI recv(
      [in]  SOCKET s,                       // 接收端socket的描述符
      [out] char   *buf,                    // 准备存放接收数据的缓存位置
      [in]  int    len,                     // 接收缓存的长度
      [in]  int    flags                    // 指定调用方式的标志,用按位或运算得出,通常为0
    );                                      // 若成功则返回实际接收的字节数,
                                            // 否则返回SOCKET_ERROR
    
    // 发送 (不需要连接)
    int WSAAPI sendto(
      [in] SOCKET         s,                // 发送端socket的描述符
      [in] const char     *buf,             // 存有准备发送数据的缓存位置
      [in] int            len,              // 要发送数据的字节数
      [in] int            flags,            // 指定调用方式的标志,用按位或运算得出,通常为0
      [in] const sockaddr *to,              // 保存接收端信息的sockaddr结构体的位置,可选
      [in] int            tolen             // sockaddr结构体的长度,可选
    );                                      // 若成功则返回实际发送的字节数,
                                            // 否则返回SOCKET_ERROR
    
    // 接收 (不需要连接)
    int WSAAPI recvfrom(
      [in]  SOCKET                 s,       // 接收端socket的描述符
      [out] char                   *buf,    // 准备存放接收数据的缓存位置
      [in]  int                    len,     // 接收缓存的长度
      [in]  int                    flags    // 指定调用方式的标志,用按位或运算得出,通常为0
      [out]               sockaddr *from,   // 保存接收端信息的sockaddr结构体的位置,可选
      [in, out, optional] int      *fromlen // sockaddr结构体的长度,可选
    );                                      // 若成功则返回实际接收的字节数,
                                            // 否则返回SOCKET_ERROR
    
    
    /*
        简单示例
    */
    
    /* socket已连接时 */
    
    // 声明变量
    char SendBuf[1024];                     // 声明一个发送数据缓存
    int SendBufLen = 1024;                  // 发送数据缓存长度
    char RecvBuf[1024];                     // 声明一个接收数据缓存
    int RecvBufLen = 1024;                  // 接收数据缓存长度
    
    // 发送数据
    send(sock, SendBuf, SendBufLen, 0);
    
    // 接收数据
    recv(sock, RecvBuf, RecvBufLen, 0);
    
    /* socket无连接时,也可用于已连接的socket,此时最后两个参数为NULL */
    
    // 声明变量
    char SendBuf[1024];                     // 声明一个发送数据缓存
    int SendBufLen = 1024;                  // 发送数据缓存长度
    char RecvBuf[1024];                     // 声明一个接收数据缓存
    int RecvBufLen = 1024;                  // 接收数据缓存长度
    sockaddr_in RecvAddr;                   // 声明一个用于保存接收端信息的sockaddr_in结构体
    sockaddr_in SendAddr;                   // 声明一个用于保存发送端信息的sockaddr_in结构体
    
    // 将接收端的信息更新到sockaddr_in结构体中
    RecvAddr.sin_family = AF_INET;
    RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    RecvAddr.sin_port = htons(27015);
    
    // 将服务器端的信息更新到sockaddr_in结构体中
    SendAddr.sin_family = AF_INET;
    SendAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    SendAddr.sin_port = htons(27015);
    
    // 发送数据
    sendto(sock, SendBuf, SendBufLen, 0, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
    
    // 接收数据
    recvfrom(sock, RecvBuf, RecvBufLen, 0, (SOCKADDR *) & SendAddr, sizeof (SendAddr));

    4. 关闭socket

    /*
        方法
    */
    
    // 关闭指定的socket功能,而不是socket本身,TCP会在传输结束后发送FIN报文段
    int WSAAPI shutdown(
      [in] SOCKET s,                        // 准备关闭功能的socket的描述符
      [in] int    how                       // 准备关闭的功能的枚举
    );                                      // 若成功则返回0,否则返回SOCKET_ERROR
    
    // 关闭socket,TCP会直接发送FIN报文段,可能导致缓存区内数据丢失
    int WSAAPI closesocket(
      [in] SOCKET s                         // 准备关闭的socket的描述符
    );                                      // 若成功则返回0,否则返回SOCKET_ERROR
    
    
    /*
        简单示例
    */
    
    // 关闭socket的发送功能
    shutdown(sock, SD_SEND);
    
    // 关闭socket的接收功能
    shutdown(sock, SD_RECEIVE);
    
    // 关闭socket的所有功能
    shutdown(sock, SD_BOTH);
    
    // 关闭socket
    closesocket(sock);

    5. 服务器端完整示例

    #ifndef UNICODE
    #define UNICODE
    #endif
    
    #define WIN32_LEAN_AND_MEAN
    
    #include <winsock2.h>
    #include <Ws2tcpip.h>
    #include <stdio.h>
    
    // Link with ws2_32.lib
    #pragma comment(lib, "Ws2_32.lib")
    
    #define DEFAULT_BUFLEN 512
    #define DEFAULT_PORT 27015
    
    int main() {
    
        //----------------------
        // 声明并初始化socket
        SOCKET ListenSocket = INVALID_SOCKET;
        SOCKET AcceptSocket = INVALID_SOCKET;
    
        // 声明sockaddr_in结构体并更新服务器端信息
        sockaddr_in service;
        service.sin_family = AF_INET;
        service.sin_addr.s_addr = inet_addr("127.0.0.1");
        service.sin_port = htons(27015);
    
        // 声明并初始化测试用发送和接收缓存
        char *sendbuf = "This is a test from server";
        int recvbuflen = DEFAULT_BUFLEN;
        char recvbuf[DEFAULT_BUFLEN] = "";
    
        // 声明结果接收变量
        int iResult;
    
        //----------------------
        // 初始化Windows Socket 2
        WSADATA wsaData;
        iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
        if (iResult != NO_ERROR) {
            printf("WSAStartup failed with error: %d\n", iResult);
            return 1;
        } else
            printf("Windows Socket 2 initialized.");
    
        //----------------------
        // 创建监听socket
        ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (ListenSocket == INVALID_SOCKET) {
            printf("Socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }
    
        // 绑定监听socket
        if (bind(ListenSocket, (SOCKADDR *) & service, sizeof (service)) == SOCKET_ERROR) {
            printf("Bind failed with error: %ld\n", WSAGetLastError());
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }
    
        // 开始监听
        if (listen(ListenSocket, 1) == SOCKET_ERROR) {
            printf("Listen failed with error: %ld\n", WSAGetLastError());
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        } else
            printf("Waiting for client to connect...\n");
    
        // 等待客户端发起连接后建立尝试连接
        AcceptSocket = accept(ListenSocket, NULL, NULL);
        if (AcceptSocket == INVALID_SOCKET) {
            printf("Accept failed with error: %ld\n", WSAGetLastError());
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        } else
            printf("Client connected.\n");
    
        //----------------------
        // 发送一个测试数据
        iResult = send(AcceptSocket, sendbuf, (int)strlen(sendbuf), 0);
        if (iResult == SOCKET_ERROR) {
           printf("Send failed with error: %d\n", WSAGetLastError());
            closesocket(AcceptSocket);
            WSACleanup();
            return 1;
        } else
            printf("Bytes sent: %d\n", iResult);
    
        // 发送完成后关闭发送功能
        iResult = shutdown(AcceptSocket, SD_SEND);
        if (iResult == SOCKET_ERROR) {
            printf("Shutdown failed with error: %d\n", WSAGetLastError());
            closesocket(AcceptSocket);
            WSACleanup();
            return 1;
        }
    
        // 持续接收数据直到对方发送完所有数据
        do {
            iResult = recv(AcceptSocket, recvbuf, recvbuflen, 0);
            if (iResult > 0)
                printf("Bytes received: %d\n", iResult);
            else if (iResult == 0)
                printf("Connection closed.\n");
            else
                printf("recv failed with error: %d\n", WSAGetLastError());
        } while (iResult > 0);
    
        //----------------------
        // 关闭连接
        iResult = closesocket(AcceptSocket);
        if (iResult == SOCKET_ERROR) {
            printf("close failed with error: %d\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }
    
        WSACleanup();
        return 0;
    }

     5. 客户端完整示例

    #ifndef UNICODE
    #define UNICODE
    #endif
    
    #define WIN32_LEAN_AND_MEAN
    
    #include <winsock2.h>
    #include <Ws2tcpip.h>
    #include <stdio.h>
    
    // Link with ws2_32.lib
    #pragma comment(lib, "Ws2_32.lib")
    
    #define DEFAULT_BUFLEN 512
    #define DEFAULT_PORT 27015
    
    int main() {
    
        //----------------------
        // 声明并初始化socket
        SOCKET ConnectSocket = INVALID_SOCKET;
    
        // 声明sockaddr_in结构体并更新服务器端信息
        sockaddr_in service;
        service.sin_family = AF_INET;
        service.sin_addr.s_addr = inet_addr("127.0.0.1");
        service.sin_port = htons(27015);
    
        // 声明并初始化测试用发送和接收缓存
        char *sendbuf = "This is a test from client";
        int recvbuflen = DEFAULT_BUFLEN;
        char recvbuf[DEFAULT_BUFLEN] = "";
    
        // 声明结果接收变量
        int iResult;
    
        //----------------------
        // 初始化Windows Socket 2
        WSADATA wsaData;
        iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
        if (iResult != NO_ERROR) {
            printf("WSAStartup failed with error: %d\n", iResult);
            return 1;
        } else
            printf("Windows Socket 2 initialized.");
    
        //----------------------
        // 创建socket
        ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (ConnectSocket == INVALID_SOCKET) {
            printf("Socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }
    
        // 连接到服务器端
        iResult = connect(ConnectSocket, (SOCKADDR*) &service, sizeof(service));
        if (iResult == SOCKET_ERROR) {
            printf("Connect failed with error: %d\n", WSAGetLastError());
            closesocket(ConnectSocket);
            WSACleanup();
            return 1;
        } else
            printf("Server connected.");
    
        //----------------------
        // 发送一个测试数据
        iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
        if (iResult == SOCKET_ERROR) {
           printf("Send failed with error: %d\n", WSAGetLastError());
            closesocket(ConnectSocket);
            WSACleanup();
            return 1;
        } else
            printf("Bytes sent: %d\n", iResult);
    
        // 发送完成后关闭发送功能
        iResult = shutdown(ConnectSocket, SD_SEND);
        if (iResult == SOCKET_ERROR) {
            printf("Shutdown failed with error: %d\n", WSAGetLastError());
            closesocket(ConnectSocket);
            WSACleanup();
            return 1;
        }
    
        // 持续接收数据直到对方发送完所有数据
        do {
            iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
            if (iResult > 0)
                printf("Bytes received: %d\n", iResult);
            else if (iResult == 0)
                printf("Connection closed.\n");
            else
                printf("recv failed with error: %d\n", WSAGetLastError());
        } while (iResult > 0);
    
        //----------------------
        // 关闭连接
        iResult = closesocket(ConnectSocket);
        if (iResult == SOCKET_ERROR) {
            printf("close failed with error: %d\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }
    
        WSACleanup();
        return 0;
    }

    二、Socket的通信流程

            在了解了Windows环境下使用的Windows Socket 2中的一些常用API后,还需要简单地介绍一下TCP和UDP使用socket进行通信时的流程。

    1. TCP使用socket的通信流程

            当使用TCP时,服务器端需要先调用WSAStartup()进行初始化,然后调用socket()和bind()创建一个服务器端的master socket并与端口绑定,再调用listen()来开启监听,最后调用accept()阻塞线程并等待客户端发起连接。而客户端则只需要使用socket()创建一个socket,不需要进行绑定。因为在发送数据时,未绑定的socket会被自动分配一个空闲的端口进行绑定。相反,若客户端选择手动绑定端口,则需要首先确认当前端口是否已被占用,使用起来更加麻烦。客户端在成功创建socket之后,需要调用connect()方法向服务器端发起连接,而服务器端阻塞的accept()在收到客户端发起的连接后新建一个socket与客户端的socket连接并进行通信。此时服务器端新建的socket和客户端的socket都为connected socket,通常服务器端的connected socket会被交给一个新开辟的线程进行管理。此时双方通常会调用send()和recv()来进行数据传递,不过sendto()和recvfrom()同样适用于这种情况,只是方法中的后两个参数会被置为NULL。当任何一方数据发送完成后,会调用shutdown()关闭socket的发送功能。当缓存中的所有数据发送完后,TCP会发送FIN报文段,而对方的recv()则会返回0。此时对方可以选择调用shutdown()关闭socket的接收功能,或是在已经关闭发送功能时选择直接调用closesocket()关闭socket。

    2. UDP使用socket的通信流程

            当使用UDP时,服务器端在调用WSAStartup()进行初始化后,只需要使用socket()和bind()创建一个服务器端的socket并与端口绑定,就可以开始等待接收数据。客户端则和使用TCP时一样,只需要使用socket()进行创建,而不需要进行绑定。在双方socket都创建完成后,客户端可以选择通过sendto()和recvfrom()来直接进行数据的交互,也可以选择先调用connect()后再使用send()和recv()来进行数据的传递。但是与TCP中使用connect()时不同,UDP本身并不需要建立连接,也不会像TCP一样进行三次握手,因此调用connect()并不会与对方建立实际的连接,而只是创建了默认的目的地地址信息供send()和recv()使用。或者换句话说,调用connect()后,客户端的socket与服务器端的socket建立了传输层以上的、形式上的连接。而使用以上两种方式进行数据交互的不同在于,使用sendto()和recvfrom()来进行交互的底层是,每次的数据传输都需要经过建立连接、发送数据和关闭连接三个步骤;而在调用connect()后再使用send()和recv()来进行交互就不需要多次的建立和关闭连接,而是可以连续发送数据。当客户端完成数据的发送后,同样会调用shutdown()关闭socket的发送功能,再调用closesocket()关闭socket。

    展开全文
  • 计算机网络——Socket实验2

    千次阅读 2022-04-17 01:51:52
    掌握Socket的TCP通信、 Socket的UDP通信 二、实验内容 Socket、ServerSocket类和DatagramPacket 、DatagramSocket类的使用 三、实验环境 使用Windows操作系统;Internet连接 IDEA+Java开发环境 四、实验...
  • 实验三 socket套接字编程实验一、Sockets编程基础知识网络编程就是通过计算机网络与其他程序进行通信的程序,Socket编程是网络编程的主流工具。Socket API是实现进程间通信的一种编程设施,也是一种为进程间提供底层...
  • 计算机写的网络套接字,希望对你有所帮助!!!
  • 计算机网络Socket网络编程实验 写在开头 :实验写完好久了,一直没抽出时间写这个博客 还是太懒了啊 注:这次实验代码仅供参考学习,照搬抄袭不可取,有可能实验0分 5-1 Socket网络编程 题目: 1.使用InetAddress类的...
  • 计算机网络协议(三)——UDP、TCP、Socket

    万次阅读 多人点赞 2019-09-04 08:39:53
    这个专栏的计算机网络协议,我是在极客时间上学习 已经有三万多人购买的刘超老师的趣谈网络协议专栏,讲的特别好,像看小说一样学习到了平时很枯燥的知识点,计算机网络的书籍太枯燥,感兴趣的同学可以去付费购买,...
  • 计算机网络课程实验及课程设计内容,基于Socket编程,实现文件传输。
  • 计算机网络原理-TCP协议和UDP协议的的Socket编程实现(内含C语言,Java,python三种语言实现源码+实验报告书
  • 计算机网络 23】Socket技术详解

    千次阅读 2021-02-03 20:31:40
    通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据  socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> ...
  • A server and client for TCP communication. Socket Programming Written in C++ 分为Windows版和Linux版,project要求是那个文档,希望对大家有所帮助
  • 利用C++语言,分别基于TCP和UDP编写一个简单的Client/Server网络应用程序。要求实现客户向服务器传输任意一个字符串,服务器将收到的字符串变换成大写后传回客户。修改上述程序,实现服务器根据客户请求,将服务器端...
  • 计算机网络课程实际,基于soket编程的网络聊天室
  • 只包含源代码部分(需要重新编译) 实验软件:Window10,VS2019 实验硬件: Intel® Core™ i5-8250U CPU @1.60GHz 1.80GHz
  • 计算机网络实验SOCKET编程----WEB服务器[C#版本].rar计算机网络实验SOCKET编程----WEB服务器[C#版本].rar
  • C++实现,MFC应用程序。客户端与服务器之间进行数据传输,源码打包了,直接运行就行,绝对满足老师的要求,代码部分有注释,容易看懂。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 122,629
精华内容 49,051
关键字:

计算机网络socket