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 初始化失败!\n");
    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\n" , argv[0]);
        return -1;
    }


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

    /*创建Socket*/
    sClient = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
    if (sClient == INVALID_SOCKET) {
        printf("socket() 失败: %d\n" , 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\n" , 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\n" , 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\n" , WSAGetLastError());
            break;
        }
        printf("Send %d bytes\n" , ret);
        //接收从服务器来的消息
        ret = recv(sClient , Buffer , BUFSIZE , 0);
        if (ret == 0) {
            break;
        }
        else if (ret == SOCKET_ERROR) {
            printf("recv() 失败: %d\n" , WSAGetLastError());
            break;
        }
        Buffer[ret] = '\0';
        printf("Recv %d bytes:\n\t%s\n" , 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\n" , WSAGetLastError());
 24             break;
 25         }
 26         Buffer[ret] = '\0';
 27         printf("Recv: %s\n" , 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\n" , 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\n" , argv[0]);
 60         return -1;
 61     }
 62 
 63     /*加载Winsock DLL*/
 64     if (WSAStartup(MAKEWORD(2 , 2) , &wsd) != 0) {
 65         printf("WinSock 初始化失败!\n");
 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\n" , 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\n" , 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\n" , WSAGetLastError());
101             break;
102         }
103         printf("接受客户端连接: %s:%d\n" ,
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\n" , 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 代码

 

posted @ 2015-07-01 15:13  乌合之众  阅读(18772)  评论(2编辑  收藏  举报
clear