已经很久没有在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的,因为都是局域网内,就简单的写了个。
这里是在虚拟机里面测试的截图,代码见最后。

windows下的socket网络编程

 

代码如下

这是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 代码

相关文章: