• windows下的socket网络编程


    windows下的socket网络编程

    已经很久没有在windows下编程了,这次因为需要做一个跨平台的网络程序,就先写了个简单的winSocket网路通信的例子,以便以后用到的时候有个参考。

    windows下使用winsock编程与linux/unix的区别在于windows下需要先有一个初始化的操作,结束的时候需要一个清理的操作。还有windows下编译的时候需要连接ws32_lib库。

    大致过程如下

    • 1、初始化

      /*加载Winsock DLL*/
      WSADATA wsd;
      if (WSAStartup(MAKEWORD(2 , 2) , &wsd) != 0) {
      printf("Winsock 初始化失败! ");
      return 1;
      }

    • 2、socket相关函数调用

      socket(...)
      bind(...)
      listen(...)
      connect(...)
      accept(...)
      send/sendto
      recv/recvfrom

    • 3、清理
      WSACleanup();

    clinet.c 客户端

    客户端的流程很简单。

    • 1、先是使用socket函数产生一个打开的socket文件描述符。
    • 2、使用connect函数去连接服务端
    • 3、使用read/recv等读文件函数从服务端接收数据,使用write/send等写文件的函数向服务端发送数据

    上面是典型的TCP编程流程,如果是UDP的话不需要connect去连接服务端直接使用sendto函数来发送数据,使用recvfrom接收来自服务器的数据

    server.c 服务器端

    服务器端的流程比客户端稍微复杂一点

    • 1、调用socket打开一个socket句柄
    • 2、调用bind来绑定socket句柄到一个网口的某个端口
    • 3、调用listen来设置(启用)监听
    • 4、调用accept来等待客户端的连接

    上面是典型的TCP编程流程,如果是UDP的,那么不需要3,4这两部,直接使用recvfrom来接收客户端发过来的数据即可。

    UDP通信的实现

    我这里没有写TCP的,因为都是局域网内,就简单的写了个。
    这里是在虚拟机里面测试的截图,代码见最后。

    代码如下

    这是TCP的,UDP的就不贴了。

    #include <winsock2.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #pragma comment(lib , "ws2_32.lib")
    
    #define BUFSIZE 4096 /*缓冲区大小*/
    
    int main_client(int argc , char *argv[])
    {
        WSADATA wsd;
        SOCKET sClient;
        char Buffer[BUFSIZE];
        int ret;
        struct sockaddr_in server;
        unsigned short port;
        struct hostent *host = NULL;
    
        if (argc < 3) {
            printf("Usage:%s IP Port
    " , argv[0]);
            return -1;
        }
    
    
        /*加载Winsock DLL*/
        if (WSAStartup(MAKEWORD(2 , 2) , &wsd) != 0) {
            printf("Winsock    初始化失败!
    ");
            return 1;
        }
    
        /*创建Socket*/
        sClient = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
        if (sClient == INVALID_SOCKET) {
            printf("socket() 失败: %d
    " , WSAGetLastError());
            return 1;
        }
        /*指定服务器地址*/
        server.sin_family = AF_INET;
        port = atoi(argv[2]);
        server.sin_port = htons(port);
        server.sin_addr.s_addr = inet_addr(argv[1]);
    
        if (server.sin_addr.s_addr == INADDR_NONE) {
            host = gethostbyname(argv[1]);    //输入的地址可能是域名等
            if (host == NULL) {
                printf("无法解析服务端地址: %s
    " , argv[1]);
                return 1;
            }
            CopyMemory(&server.sin_addr ,
                        host->h_addr_list[0] ,
                        host->h_length);
        }
        /*与服务器建立连接*/
        if (connect(sClient , (struct sockaddr*)&server ,
                        sizeof(server)) == SOCKET_ERROR) {
            printf("connect() 失败: %d
    " , WSAGetLastError());
            return 1;
        }
    
        /*发送、接收消息*/
    
        for (;;) {
            //从标准输入读取要发送的数据
            //gets_s(Buffer,BUFSIZE);
            gets(Buffer);
            //向服务器发送消息
            ret = send(sClient , Buffer , strlen(Buffer) , 0);
            if (ret == 0) {
                break;
            }
            else if (ret == SOCKET_ERROR) {
                printf("send() 失败: %d
    " , WSAGetLastError());
                break;
            }
            printf("Send %d bytes
    " , ret);
            //接收从服务器来的消息
            ret = recv(sClient , Buffer , BUFSIZE , 0);
            if (ret == 0) {
                break;
            }
            else if (ret == SOCKET_ERROR) {
                printf("recv() 失败: %d
    " , WSAGetLastError());
                break;
            }
            Buffer[ret] = '';
            printf("Recv %d bytes:
    	%s
    " , ret , Buffer);
    
        }
        //用完了,关闭socket句柄(文件描述符)
        closesocket(sClient);
        WSACleanup();    //清理
        return 0;
    }
    查看 clinet.c 代码
      1 #include <winsock2.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 
      5 #pragma comment(lib , "ws2_32.lib")
      6 
      7 
      8 #define DEFAULT_BUFFER 4096 /*缓冲区大小*/
      9 
     10 
     11 /*与客户机通信的线程函数*/
     12 DWORD WINAPI ClientThread(LPVOID lpParam)
     13 {
     14     SOCKET sock = (SOCKET)lpParam;
     15     char Buffer[DEFAULT_BUFFER];
     16     int ret , nLeft , idx;
     17     while (1) {
     18         /*接收来自客户机的消息*/
     19         ret = recv(sock , Buffer , DEFAULT_BUFFER , 0);
     20         if (ret == 0)
     21             break;
     22         else if (ret == SOCKET_ERROR) {
     23             printf("recv() 失败: %d
    " , WSAGetLastError());
     24             break;
     25         }
     26         Buffer[ret] = '';
     27         printf("Recv: %s
    " , Buffer);    //打印接收到的消息
     28 
     29 
     30         nLeft = ret;
     31         idx = 0;
     32         while (nLeft > 0) {
     33             /*向客户机发送回应消息*/
     34             ret = send(sock , &Buffer[idx] , nLeft , 0);
     35             if (ret == 0)
     36                 break;
     37             else if (ret == SOCKET_ERROR) {
     38                 printf("send() 失败: %d
    " , WSAGetLastError());
     39                 break;
     40             }
     41             nLeft -= ret;
     42             idx += ret;
     43         }
     44     }
     45     return 0;
     46 }
     47 
     48 int main_server(int argc , char **argv)
     49 {
     50     WSADATA        wsd;
     51     HANDLE        hThread;
     52     DWORD        dwThread;
     53     SOCKET        sListen , sClient;
     54     int            AddrSize;
     55     unsigned short port;
     56     struct sockaddr_in local , client;
     57 
     58     if (argc < 2) {
     59         printf("Usage:%s Port
    " , argv[0]);
     60         return -1;
     61     }
     62 
     63     /*加载Winsock DLL*/
     64     if (WSAStartup(MAKEWORD(2 , 2) , &wsd) != 0) {
     65         printf("WinSock 初始化失败!
    ");
     66         return 1;
     67     }
     68 
     69     /*创建Socket*/
     70     sListen = socket(AF_INET , SOCK_STREAM , IPPROTO_IP);
     71     if (sListen == SOCKET_ERROR) {
     72         printf("socket() 失败: %d
    " , WSAGetLastError());
     73         return 1;
     74     }
     75 
     76     local.sin_family = AF_INET;
     77     local.sin_addr.s_addr = htonl(INADDR_ANY);
     78     port = atoi(argv[1]);    //获取端口值
     79     local.sin_port = htons(port);
     80 
     81     /*绑定Socket*/
     82     if (bind(sListen ,
     83         (struct sockaddr*)&local ,
     84         sizeof(local)) == SOCKET_ERROR) {
     85         printf("bind() 失败: %d
    " , WSAGetLastError());
     86         return 1;
     87     }
     88     /*打开监听*/
     89     listen(sListen , 8);
     90 
     91     /*在端口进行监听,一旦有客户机发起连接请示
     92     就建立与客户机进行通信的线程*/
     93     while (1) {
     94         AddrSize = sizeof(client);
     95         /*监听是否有连接请求*/
     96         sClient = accept(sListen ,
     97                          (struct sockaddr*)&client ,
     98                          &AddrSize);
     99         if (sClient == INVALID_SOCKET) {
    100             printf("accept() 失败: %d
    " , WSAGetLastError());
    101             break;
    102         }
    103         printf("接受客户端连接: %s:%d
    " ,
    104                inet_ntoa(client.sin_addr) ,
    105                ntohs(client.sin_port));
    106 
    107         //创建一个线程去处理
    108         hThread = CreateThread(NULL , 0 , ClientThread ,
    109                                (LPVOID)sClient , 0 , &dwThread);
    110 
    111         if (hThread == NULL) {
    112             printf("CreateThread() 失败: %d
    " , GetLastError());
    113             break;
    114         }
    115         //处理完后关闭
    116         CloseHandle(hThread);
    117     }
    118     closesocket(sListen);
    119     WSACleanup();    //用完了要清理
    120     return 0;
    121 }
    查看 server.c 代码

    测试代码(main)

     1 extern int main_client(int , char**);
     2 extern int main_server(int , char**);
     3 
     4 int main(int c , char** v)
     5 {
     6     if (c == 3) {
     7         main_client(c , v);
     8     }
     9     else {
    10         main_server(c , v);
    11     }
    12     return 0;
    13 
    14 }
    查看 test 代码
  • 相关阅读:
    生活娱乐 工业机器人代替工人装配鼠标键盘
    生活娱乐 工商银行如何查询开户行
    生活娱乐 格力空气能热水器怎么样
    生活娱乐 岛城将开首家机器人餐厅
    生活娱乐 毕业生论文查重技巧
    Windows 老是弹出要自动拨号连接怎么办
    Office 针式打印机如何调节边距
    Office 如何打印彩色照片能取得较好的效果
    西游释厄传如何设置简化出招表
    [ES2019] Use JavaScript ES2019 flatMap to Map and Filter an Array
  • 原文地址:https://www.cnblogs.com/oloroso/p/4613296.html
Copyright © 2020-2023  润新知