zoukankan      html  css  js  c++  java
  • Socket网络编程(一)

    此文使用的协议是 TCP

        首先要写入以下代码,不然很多函数都用不了

    #include <WinSock2.h>
    #pragma comment(lib, "ws2_32.lib")

    服务器端

        第一步我们要导入套接字库。

    WORD wVersionRequested = MAKEWORD(1, 1);
    WSADATA wsadata;
    int result = WSAStartup(wVersionRequested, &wsadata);

    WORD有人可能不知道它是啥

    看一看源代码就可以看到它是这样定义的

    typedef unsigned short WORD   //无符号短整数

    还有WSAStartup函数,它的原型是这样的

    int WSAStartup(WORD wVersionRequested,LPWSADATA IpWSAData);

    第一个参数表示windows socket版本,高字节是修订版本号,低字节是主版本号;

    第二个参数记录windows socket版本的相关信息,并且是指针变量;

    这个函数有返回值,返回0时表示成功,其他值表示失败。

    有时我们写服务器时为了防止套接字库加载错误可以写以下代码

    if (result != 0)
        {
            printf("套接字加载失败!");
            return 0;
        }
    
    if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1)
        {
            printf("套接字版本错误!");
            return 0;
        }

    当然socket有不同的版本,这里只是做个示范

        第二步创建套接字SOCKET

    源代码是这样定义的

    typedef unsigned int UINT_PIR
    typedef UINT_PIR  SOCKET

    所以SOCKET也是一个无符号整型数据

    创建套接字要用到socket函数,函数原型是这样的

    SOCKET _stdcall socket(int af,int type,int protocol)

    af是address family的缩写,就是地址簇

    type就是使用的协议类型,一共有三种

    1、流式套接字(SOCK_STREAM):用到的协议TCP 

    2、数据包套接字(SOCK_DGRAM):无连接的,不可靠的UDP

    3、原始套接字(SOCK_RAW)

    而protocol就是与特定的地址簇相关的协议,一般填0就行了,现在举个例子

    SOCKET sockSrv = socket( AF_INET      //Internet 协议  地址簇
                            SOCK_STREAM, //套接字协议
                            0            //与特定的地址簇相关的协议
    );

      第三步绑定套接字

    //bind绑定套接字,参数一服务器套接字,参数二服务器套接字地址,参数三套接字地址大小
    SOCKADDR_IN sockaddr;
    sockaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_port = htons(1234);
    if (SOCKET_ERROR == bind(sockSrv, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR)))
        {
            printf("绑定套接字失败!");
            return 0;
        };

    那个 INADDR_ANY 表示的是任意地址的意思,因为服务器的地址是不确定的,所以填这个,当然你想改也可以改,只要改的对,还有端口随便找个不常用到的就行。

        第四步将套接字设置为监听模式

    //   参数一服务器套接字,参数二等待连接队列最大长度
    if (SOCKET_ERROR == listen(sockSrv, 5))
        {
            printf("监听失败!");
            return 0;
        }

        第五步接受客户端

    // 参数一服务器套接字,参数二客户端套接字,参数三客户端套接字的长度
    SOCKADDR_IN clientaddr;
    int nLength = sizeof(SOCKADDR);
    SOCKET sockcon = accept(sockSrv, (SOCKADDR*)&clientaddr, &nLength);

        第六步发送/接受信息

    函数原型int_stdcall send(SOCKET s,const char *buf,int len,int flags)

    随便举个例子

    char temp[100];
    sprintf(temp, "欢迎 %s 进入聊天室!
    ", inet_ntoa(clientaddr.sin_addr));//字符串是客户端的地址
    send(sockCon, temp, strlen(temp) + 1, 0);
    char temp[256];
    recv(sockCon, tmep, 100, 0) 
    printf("%s", temp);

        最后要记得关闭套接字,不然有时会出现意外情况

    closesocket(sock);
    WSACleanup();

    ●客户端

        第一步与服务器端一样加载套接字库,就不说了

        第二步创建套接字

    SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0);

        第三步连接服务器

    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//测试所以就用本地的了
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(1234); //端口随便写一个1024之后的,也就是不常用的,不过要与服务器的一样
    //参数一客户端套接字,参数二服务器地址信息,参数三套接字地址大小
    if (SOCKET_ERROR == connect(sockCli, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)))
        {
            printf("服务器连接失败!");
            return 0;
        }

        第四步发送/接受信息,与之前的一样,也不说了

       当然最后也别忘了关闭套接字

  • 相关阅读:
    Keepalived安装配置
    Playbook 角色(Roles) 和 Include 语句
    Ansible Playbook
    ansible的Ad-hoc命令
    Android线程简介
    宝岛探险,DFS&BFS
    再解炸弹人,dfs&bfs
    解救小哈——bfs广搜
    解救小哈——dfs深搜
    数的全排列
  • 原文地址:https://www.cnblogs.com/hemou/p/9805782.html
Copyright © 2011-2022 走看看