2017-05-29 18:43:01 c914620529 阅读数 2848

TCPIP很方便实现局域网或外网的通信,分客户端和服务端,其实也可以把客户端和服务端写到一起,既可以做服务也可以做客户端,基本流程就是,服务监听一个端口,收到客户端的链接请求以后,链接通信就行了

通信模式分为UDP和TCP  就是广播和定点通信,UDP模式不管收没收到 只管把信息发出去,TCP是稳定的 固定的通信

具体用法和实现可以自己去查查,这次用到的是TCP模式。

TCP也有长连接短链接   其实没啥区别  一个通信完断开 一个保持链接

我用的这个服务不是正经的封装,自己做测试用的,大家用到的看看就行了,客户端也就两句话

大家可以看看是什么个过程然后自己再改


客户端下载

http://download.csdn.net/detail/c914620529/9855481


服务端下载

http://download.csdn.net/detail/c914620529/9855486

2019-08-17 22:34:48 yimiyangguang185 阅读数 94

tcpip通信server端的c++代码


#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <sstream>
#include <errno.h>

#define SERV_PORT 8888        //服务器端口
#define SERV_IP "192.168.2.117"   //服务器ip

using namespace std;

int main(int argc,char** argv)
{

    int servfd,clitfd;   //创建两个文件描述符,servfd为监听套接字,clitfd用于数据传输
    struct sockaddr_in serv_addr,clit_addr; //创建地址结构体,分别用来存放服务端和客户端的地址信息

    memset(&serv_addr,0,sizeof(serv_addr));  //初始化
    memset(&clit_addr,0,sizeof(clit_addr));  //初始化

    if((servfd = socket(AF_INET,SOCK_STREAM,0)) == -1)  //创建套接字
    {
        cout<<"creat socket failed : "<<strerror(errno)<<endl;//如果出错则打印错误
        return 0;
    }

        //给服务端的地址结构体赋值
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERV_PORT); //将主机上的小端字节序转换为网络传输的大端字节序(如果主机本身就是大端字节序就不用转换了)
    serv_addr.sin_addr.s_addr = inet_addr(SERV_IP); //将字符串形式的ip地址转换为点分十进制格式的ip地址

        //绑定地址信息到监听套接字上,第二个参数强转是因为形参类型为sockaddr ,而实参类型是sockaddr_in 型的
    if(bind(servfd,(sockaddr *)& serv_addr,sizeof(serv_addr)) == -1)
    {
        cout<<"bind failed : "<<strerror(errno)<<endl;
        return 0;
    }

        //将servfd套接字置为监听状态
    if(listen(servfd,1024) == -1)
    {
        cout<<"listen failed : "<<strerror(errno)<<endl;
        return 0;
    }

    cout<<"Init Success ! "<<endl;
    cout<<"ip : "<<inet_ntoa(serv_addr.sin_addr)<<"  port : "<<ntohs(serv_addr.sin_port)<<endl;
    cout<<"Waiting for connecting ... "<<endl;

    socklen_t clit_size = 0; //用于accept函数中保存客户端的地址结构体大小

        //accept成功后,clitfd则指向了这条服务端与客户端成功连接的”通路“
    if((clitfd = accept(servfd,(sockaddr *)& clit_addr,&clit_size)) == -1)
    {
        cout<<"accept failed : "<<strerror(errno)<<endl;
        return 0;
    }

    cout<<"Client access : "<<inet_ntoa(clit_addr.sin_addr)<<"  "<<ntohs(clit_addr.sin_port)<<endl;


    char buf[1024]; //用于读写数据

    while(1)
    {
        int rdstate;
        if((rdstate = read(clitfd,buf,sizeof(buf))) > 0 )//通过clitfd来读取数据,返回值为读取的长度
        {
            int i=0;
            cout<<"(Server)recv : ";
            for(i=0;i<rdstate;i++)
            {
                cout<<buf[i];
                buf[i] = toupper(buf[i]); //转换为大写
            }
            buf[i]='\0';
            cout<<endl;
            write(clitfd,buf,strlen(buf)); //发回客户端
        }
                else if(rdstate == 0)  //客户端退出
        {
            cout<<"client exit ! "<<endl;
            return 0;
        }
    }

    close(servfd);  //关闭套接字
    close(clitfd);
    return 0;
}

tcpip通信client段的c++代码

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>

#define MYPORT  502
#define BUFFER_SIZE 1024

int main() {
    ///定义sockfd
    int sock_cli = socket(AF_INET, SOCK_STREAM, 0);

    ///定义sockaddr_in
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(MYPORT);  ///服务器端口
    servaddr.sin_addr.s_addr = inet_addr("192.168.2.171");  ///服务器ip

    //连接服务器,成功返回0,错误返回-1
    if (connect(sock_cli, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
        perror("connect");
        exit(1);
    }

    char sendbuf[BUFFER_SIZE];
    char recvbuf[BUFFER_SIZE];
    while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) {
        send(sock_cli, sendbuf, strlen(sendbuf), 0); ///发送
        if (strcmp(sendbuf, "exit\n") == 0)
            break;
        recv(sock_cli, recvbuf, sizeof(recvbuf), 0); ///接收
        fputs(recvbuf, stdout);

        memset(sendbuf, 0, sizeof(sendbuf));
        memset(recvbuf, 0, sizeof(recvbuf));
    }

    close(sock_cli);
    return 0;
}

tcpip通信client端的c++代码(为connect()函数和recv()函数设置的最大阻塞时间10s)

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/time.h>
#include <iostream>
#include <errno.h>

#define MYPORT  502
#define BUFFER_SIZE 1024

int main() {
    ///定义sockfd
    int sock_cli = socket(AF_INET, SOCK_STREAM, 0);

    ///定义sockaddr_in
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;//该参数表示ipv4协议
    servaddr.sin_port = htons(MYPORT);  ///服务器端口
    servaddr.sin_addr.s_addr = inet_addr("192.168.2.171");  ///服务器ip

//    /** connect函数会阻塞 默认阻塞时间貌似为70秒 **/
//    //连接服务器,成功返回0,错误返回-1
//    if (connect(sock_cli, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
//        perror("connect");
//        exit(1);
//    }

    /**1.建立socket(前面代码已完成)
       2.将该socket设置为非阻塞模式
       3.调用connect()
       4.使用select()检查该socket描述符是否可写(注意,是可写)
       5.根据select()返回的结果判断connect()结果
       6.将socket设置为阻塞模式**/
    int flags;
    if((flags = fcntl(sock_cli, F_GETFL, 0)) < 0) {//备份原始的socket设置参数给flags
        perror("Netwrok test...\n");
        close(sock_cli);
        return -1;
    }
    if(fcntl(sock_cli, F_SETFL, flags | O_NONBLOCK) < 0) {//在原始参数基础上增加参数O_NONBLOCK(表示非阻塞模式)
        perror("Network test...\n");
        close(sock_cli);
        return -1;
    }

    if(connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) {
        //非阻塞模式下连接,一般会返回连接失败状态,错误码为EINPROGRESS(表示正在建立连接)
        if(errno != EINPROGRESS) { // EINPROGRESS
            perror("Network test...\n");
            close(sock_cli);
            return -1;
        }
    }
    else {
        printf("Connected\n");
        return 0;
    }

    fd_set fdr, fdw;
    FD_ZERO(&fdr);
    FD_ZERO(&fdw);
    FD_SET(sock_cli, &fdr);
    FD_SET(sock_cli, &fdw);
    struct timeval connect_timeout={10,0};//s
    
    //select()为阻塞函数,时刻查询sock_cli的状态
    int res = select(sock_cli + 1, &fdr, &fdw, NULL, &connect_timeout);

    if(res < 0) {
        perror("Network test...\n");
        close(sock_cli);
        return -1;
    }

    if(res == 0) {
        printf("Connect server timeout");
        close(sock_cli);
        return -1;
    }

    if(res == 1) {
        if(FD_ISSET(sock_cli, &fdw))
        {
            printf("Connected\n");
            //close(sock_cli);
            //return 0;
        }
    }

    if(fcntl(sock_cli, F_SETFL, flags) < 0) {
        perror("Network test...\n");
        //close(sock_cli);
        //return -1;
    }
    /****/

    //设置recv()函数最大阻塞时间
    struct timeval recving_timeout={10,0};//s
    //int ret = setsockopt(sock_cli,SOL_SOCKET,SO_SNDTIMEO,(const char*)&timeout,sizeof(timeout));
    int set_blocking_time = setsockopt(sock_cli,SOL_SOCKET,SO_RCVTIMEO,(const char*)&recving_timeout,sizeof(recving_timeout));
    if(set_blocking_time < 0){
        std::cout<<"设置recv()函数最大阻塞时间failed"<<std::endl;
    }

    char sendbuf[BUFFER_SIZE];
    char recvbuf[BUFFER_SIZE];
    //fgets()函数阻塞
    while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL) {
        send(sock_cli, sendbuf, strlen(sendbuf), 0); ///发送
        if (strcmp(sendbuf, "exit\n") == 0)
            break;
        //recv()函数阻塞
        int recvd = recv(sock_cli, recvbuf, sizeof(recvbuf), 0); ///接收
        if(recvd==-1)
        {
            std::cout<<"recv faild."<<std::endl;
        }
        fputs(recvbuf, stdout);

        memset(sendbuf, 0, sizeof(sendbuf));
        memset(recvbuf, 0, sizeof(recvbuf));
    }

    close(sock_cli);
    return 0;
}

清除cocket缓存区数据函数

/** 清除缓存区数据 **/
void cleanBuff(int sock_conn){
    // 设置select立即返回
    timeval time_out;
    time_out.tv_sec = 0;
    time_out.tv_usec = 0;

    // 设置select对sock_conn的读取感兴趣
    fd_set read_fds;
    FD_ZERO(&read_fds);
    FD_SET(sock_conn, &read_fds);

    int res = -1;
    char recv_data[2];
    memset(recv_data, 0, sizeof(recv_data));
    while(true){
        res = select(FD_SETSIZE, &read_fds, nullptr, nullptr, &time_out);
        if (res == 0) break;  //数据读取完毕,缓存区清空成功
        recv(sock_conn, recv_data, 1, 0);  //触发数据读取
    }
}

 

2016-09-02 17:43:14 mysunday2 阅读数 1547

参考之前的经验找到了代码。但是存在一定的问题在使用的时候。


原链接如下:点击打开链接


直接拷贝过去使用的时候:


1)自己的IP地址要设置为静态IP;


2)这句话原意是要引用一个库文件,但是我的没有找到,所以一直报错


什么鬼“undefined references to _gethostname@8”,烦的一笔,


在codeblocks里面settings--compiler settings--linker settings然后添加Add,弹出来一个对话框。点击右边


三个点点寻找文件


然后添加。


3)代码直接拷贝进去发现还是报错,有一些main函数返回值需要用int不是void,还有return的值也要加上去。


4)最后可以跑了以后还有个地方,server收到的字符不完整,这里client那边这么改,


    //发送数据  
    char buff = "hello, this is a Client....";  
    send(sockClient, buff, sizeof(buff), 0); 

改成:

    //发送数据  
    char buff2[50] = "hello, this is a Client....";  
    send(sockClient, buff, sizeof(buff), 0); 

反正到这里我就差不多可以用了,再有问题我也不知道了

2018-10-05 13:37:50 CodingDodo 阅读数 56

windows 10

c++网络编程学习中,对一些关键的点总结一下。


结构体


sockaddr, sockaddr_in

sockaddr和sockaddr_in区别——http://kenby.iteye.com/blog/1149001

  • sockaddr 和 sockaddr_in 同样都是为了处理网络通信的地址,包含了地址类别(familty),地址(ip),端口信息。
  • sockaddr是给机器用的,sockaddr_in给程序猿使用,手动配置
  • 大小相同,都是16bytes,可以强制转换,如(sockaddr *)&sock_addr_in_data
addrinfo

为什么需要addrinfo,stackoverflow上的讨论
配合getaddrinfo食用 - ws2tcpip.h,MS上的例子

addrinfo是一个链表结构,包含更多的地址信息,可以看成是为了准备socket的构件。

在使用getaddrinfo函数前,需要对addrinfo进行初始化

  • windows上可使用ZeroMemory(&hint, sizeof(addrinfo))
  • 或者使用memset(&hint, 0, sizeof(addrinfo))

getaddrinfo()

参数:getaddrinfo(pcstr server, pcstr service, addrinfo * hints, addrinfo **result)

  • pcstr时const char *类型(没错的话)
  • server,主机名(DESKTOP-XXX), 域名,点分十进制的ip地址
  • Service Name, 如tcp,udp,或者端口
  • hints,用于搜索过滤,如指定ai_family = AF_INET 或者 AF_INET6过滤ipv4和ipv6,等等
  • result, 搜索的结果,链表的head

小结

如果地址比较简单,就手动配置sockaddr_in

否则就是用addrinfo( getaddrinfo函数 )来配置,通过hints来过滤信息,所有的结果保存在result链表中,

2016-05-24 17:25:21 grand_duke 阅读数 224

最近做了Gprs的通讯项目,下位机已经完成接手上位机的编写,属于赶鸭子上架现学现卖了。

socket入门推荐一个文件Socket函数。chm帮助文件,通过这个文件你可以快速的上手Socket编程,里边详尽的解释了函数的功能以及使用方法。

首先解释几个名词1、有连接TCP和无连接的数据报UDP,所谓有连接也就意味着每次进行数据发送的时候都要进行地址确定发送参数包含目标地址


一、基于TCP

(1)打开Socket

调用Socket函数创建或则打开Socket

socket(): 建立Socket。
格 式: SOCKET PASCAL FAR socket( int af,int type,int protocol );
参 数: af 目前只提供 PF_INET(AF_INET),type Socket 的型态 (SOCK_STREAM、SOCK_DGRAM),protocol 通讯协定(如果使用者不指定则设为0)
传回值: 成功 - Socket 的识别码失败 - INVALID_SOCKET(呼叫 WSAGetLastError() 可得知原因)
说明: 此函式用来建立一 Socket,并为此 Socket 建立其所使用的资源。 Socket 的型态可为 Stream Socket 或 Datagram Socket。
SOCK_STREAM  TCP连接  SOCK_DGRAM  UDP连接


(2)命名Socket

sockaddr_in  socket的数据结构、

首先初始化结构团体然后调用bind函数进行Socket命名

bind(): 指定 Socket 的 Local 位址 (Address)。
格 式: int PASCAL FAR bind( SOCKET s,const struct sockaddr FAR *name,int namelen );
参 数: s Socket的识别码 name Socket的位址值,其格式为 struct sockaddr { u_short sa_family; char sa_data[14]; }; namelen name的长度
传回值: 成功 - 0 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此一函式是指定 Local 位址及 Port 给某一未定名之 Socket。使用者若不在意位址或 Port 的值,那麽他可以设定位址为 INADDR_ANY,及Port 为 0;那麽Windows Sockets 会自动将其设定适当之位址及 Port(1024 到 5000之间的值),使用者可以在此 Socket 真正连接完成後,呼叫 getsockname() 来获知其被设定的值。

(3)与另一个Socket建立关联

一个UDP服务器是无需为客户端做任何准备工作因为关联是在接收数据时建立起来的 。

但是对于一个TCP的服务器通过listen函数做准备

listen(): 设定 Socket 为监听状态,准备被连接。
格 式: int PASCAL FAR listen( SOCKET s, int backlog );
参 数: s Socket 的识别码,backlog 未真正完成连接前(尚未呼叫 accept() 前)彼端的连接要求的最大个数
传回值: 成功 - 0 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 使用者可利用此函式来设定 Socket 进入监听状态,并设定最多可有多少个在未真正完成连接前的彼端的连接要求。(目前最大值限制为 5, 最小值为1)
调用listen函数后需要调用accept函数或则select函数进行数据的接收

accept函数适用于单个客户端,select函数适用于较多的客户端

accept: 接受某一Socket的连接要求,以完成 Stream Socket 的连接。
格 式: SOCKET PASCAL FAR accept(SCOKET s,struct sockaddr FAR *addr,int FAR *addrlen);
参 数: s Socket的识别码;addr 存放来连接的彼端的位址; addrlen addr的长度
传回值: 成功 - 新的Socket识别码 失败 - INVALID_SOCKET (呼叫 WSAGetLastError() 可得知原因)
说明: Server 端之应用程式呼叫此一函式来接受 Client 端要求之Socket 连接动作;如果Server 端之 Socket 是为 Blocking 模式,且没有人要求连接动作,那麽此一函式会Block 函式马上回覆错误。accept() 函式的答覆值为一新的 Socket,此 Socket 不可再用来接受其它的连接要求;但是原先之 Socket 仍可接受其他人的连接要求。

select(): 检查一或多个 Sockets 是否处於可读、可写或错误的状态。
格 式: int PASCAL FAR select( int nfds,fd_set FAR *readfds,fd_set FAR *writefds,fd_set FAR *exceptfds,const struct timeval FAR *timeout );
参 数: nfds 此参数在此并无作用,readfds 要被检查是否可读的 Sockets,writefds 要被检查是否可写的 Sockets,exceptfds 要被检查是否有错误的 Sockets,timeout 此函式该等待的时间。若为 NULL 时,表示 blocking,此函式会等到有事件发生。
传回值: 成功 - 符合条件的 Sockets 总数 (若 Timeout 发生,则为 0) 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 使用者可利用此函式来检查 Sockets 是否有资料可被读取,或是有空间可以写入,或是有错误发生。

客户端发起关联

对于UDP的客户端

1)如果向不同的服务器发送数据采用sendto函数

sendto(): < 将资料送到指定的目的地。/td>
格 式: int PASCAL FAR sendto( SOCKET s,const char FAR *buf,int len,int flags,const struct sockaddr FAR *to,int tolen );
参 数: s Socket 的识别码,buf 存放要传送的资料的暂存区,len buf 的长度,flags 此函式被呼叫的方式,to 资料要送达的位址,tolen to 的大小
传回值: 成功 - 送出的资料长度失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式适用於 Datagram 或 Stream Socket 来传送资料到指定的位址。对 Datagram Socket 言,若是 datagram 的大小超过限制,则将不会送出任何资料,并会传回错误值。对 Stream Socket 言,其作用与 send() 相同;参数 to 及 tolen 在此并无作用。若是传送 (transport) 系统内之储存空间不够存放这些要传送的资料,sendto() 将会被 block 住,除非该Socket 被设定为 non-blocking 模式。使用者亦须注意 sendto() 函式执行完成,并不表示资料已经成功地送抵对方了。 flags 的值可设为 MSG_DONTROUTE(*暂不提供此功能)及 MSG_OOB 的组合. 本系统(WinKing)提供之 Windows Sockets API 介面乃是依照 1993年1月20日公布之 WINSOCK 第1.1版(如附录)中所定义之函式 (routine); 包括了30个Berkeley Software Distribution (BSD) 的函式以及16个符合 Windows Message-driven 特性的函式。
发送时将sockaddr作为发送参数


     2)第二种方法

首先初始化socket结构体

然后使用connect函数进行连接

connect(): 要求连接某一Socket到指定的对方。
格 式: int PASCAL FAR connect( SOCKET s,const struct sockaddr FAR *name,int namelen );
参 数: s Socket 的识别码 name 此 Socket 想要连接的对方位址 namelen name的长度
传回值: 成功 - 0 失败 - SOCKET_ERROR (呼叫WSAGetLastError()可得知原因)
说明: 此函式用来向对方要求建立连接。若是指定的对方位址为 0 的话,会传回错误值。当连接建立完成後,使用者即可利用此一 Socket 来做传送或接收资料之用了。

最后使用send函数进行发送

send(): 使用连接式的 Socket 传送资料。
格 式: int PASCAL FAR send( SOCKET s,const char FAR *buf,int len,int flags );
参 数: s Socket 的识别码,buf 存放要传送的资料的暂存区,len buf 的长度,flags 此函式被呼叫的方式
传回值: 成功 - 送出的资料长度 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式适用於连接式的 Datagram 或 Stream Socket 来传送资料。对 Datagram Socket 言,若是 datagram 的大小超过限制,则将不会送出任何资料,并会传回错误值。若是传送 (transport) 系统内之储存空间不够存放这些要传送的资料,send() 将会被 block 住,除非该 Socket 被设定为 non-blocking 模式。使用者亦须注意 send()函式执行完成,并不表示资料已经成功地送抵对方了。 flags 的值可设为 MSG_DONTROUTE(*暂不提供此功能)及 MSG_OOB 的组合.
对于UDP使用函数进行服务器的关联
recv(): 自 Socket 接收资料。
格 式: int PASCAL FAR recv( SOCKET s,char FAR *buf,int len,int flags );
参 数: s Socket 的识别码,buf 存放接收到的资料的暂存区,len buf 的长度,flags 此函式被呼叫的方式
传回值: 成功 - 接收到的资料长度 (若对方 Socket 已关闭,则为 0) 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此函式用来自连接式的 Datagram Socket 或 Stream Socket接收资料。对 Stream Socket 言,我们可以接收到目前有效的 (available)资料,但其数量不超过 len 的大小。若是此 Socket 设定 SO_OOBINLINE,且有 out-of-band 的资料未被读取,那麽只有 out-of-band 的资料被取出。对 Datagram Socket 言,只取出第一个 datagram;若是该 datagram 大於使用者提供的储存空间,那麽只有该空间大小的资料被取出,多馀的资料将遗失,且回覆错误的讯息。 flags 的值可为 MSG_PEEK、MSG_OOB(*暂不提供此功能)的组合.



(4)Socke之间进行数据的接收与发送

无论是udp还是tcp都需要调用connect函数进行发送数据准备

udp通过connect获得socket发送的地址

tcp通过connect建立虚电路


(5)关闭Socket

closedsocket

closesocket(): 关闭某一Socket
格 式: int PASCAL FAR closesocket( SOCKET s );
参 数: s Socket 的识别码
传回值: 成功 - 0 失败 - SOCKET_ERROR (呼叫 WSAGetLastError() 可得知原因)
说明: 此一函式是用来关闭某一 Socket。若是使用者原先对要关闭之 Socket 设定 SO_DONTLINGER,则在呼叫此一函式後,会马上回覆,但是此一 Sokcet 尚未传送完毕的资料会继续送完後才关闭。若是使用者原先设定此 Socket 为 SO_LINGER,则有两种情况: (a) Timeout 设为 0 的话,此一 Socket 马上重新设定 (reset),未传完或未收到的资料全部遗失。 (b) Timeout 不为 0 的话,则会将资料送完,或是等到 Timeout 发生後才关闭。
部分关闭连接使用shoutdown


shutdown(): 停止 Socket 接收/传送的功能
格 式: int PASCAL FAR shutdown( SOCKET s, int how );
参 数: s Socket 的识别码,how 代表该停止那些动作的标帜
传回值: 成功 - 0 失败 - SOCKET_ERROR (呼叫 WSAGetLastError()可得知原因)
说明: 此函式用来停止 Socket 的後续接收或传送的功能。若 how 的值为 0,则不再接收资料。若 how 的值为 1,则不再允许传送资料。若 how 的值为 2,则不再接收且不再传送资料。 shutdown() 函式并没有将 Socket 关闭,所以该 Socket 所占用之资源必须在呼叫closesocket() 之後才会释放。




没有更多推荐了,返回首页