windows网络编程-C语言实现简单的UDP协议聊天

  与TCP协议下编写服务端程序代码类似,但因为是无连接的形式,所以不需要监听。

  这次,我用了一点不同的想法:我建立一个服务端,用了两个端口和两个套接字,把服务端作为一个数据转发的中转站,使得客户机之间进行UDP协议下的通信。

  服务端代码:

/**
 *  UDP/IP 服务器端 Server.c
 */
#include <winsock2.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

#define true 1
#define false 0

#define BUFFSIZE 1024

int main(int argc, char**argv)
{
    int             Ret;
    WSADATA         wsaData;
    SOCKET          Socket_1;
    SOCKET          Socket_2;
    SOCKADDR_IN     ClientAddr_1;
    int             ClientAddr_1_Len = sizeof(ClientAddr_1);
    SOCKADDR_IN     ClientAddr_2;
    int             ClientAddr_2_Len = sizeof(ClientAddr_2);
    unsigned short  Port_1 = 5150;
    unsigned short  Port_2 = 8888;
    char            sendData[BUFFSIZE];
    char            recvData[BUFFSIZE];

    if((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
    {
        printf("WSASTARTUP_ERROR: %d
", Ret);
        exit(1);
    }

    if((Socket_1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
        printf("Socket_1_ERROR
");
        exit(1);
    }
    //将端口变量从主机字节顺序转换位网络字节顺序
    ClientAddr_1.sin_family = AF_INET;
    ClientAddr_1.sin_port = htons(Port_1);
    ClientAddr_1.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

    //使用bind将这个地址信息和套接字绑定起来
    if(bind(Socket_1, (SOCKADDR *)&ClientAddr_1, ClientAddr_1_Len) == SOCKET_ERROR)
    {
        printf("BIND_SOCKET_1_ERROR: %d
", SOCKET_ERROR);
        exit(1);
    }

    if((Socket_2 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
        printf("Socket_2_ERROR
");
        exit(1);
    }
    //将端口变量从主机字节顺序转换位网络字节顺序
    ClientAddr_2.sin_family = AF_INET;
    ClientAddr_2.sin_port = htons(Port_2);
    ClientAddr_2.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

    //使用bind将这个地址信息和套接字绑定起来
    if(bind(Socket_2, (SOCKADDR *)&ClientAddr_2, ClientAddr_2_Len) == SOCKET_ERROR)
    {
        printf("BIND_SOCKET_2_ERROR: %d
", SOCKET_ERROR);
        exit(1);
    }

    printf("建立连接成功!");

    //服务器作为中转站
    //为两个IP之间互相转发消息
    while(true)
    {
        //接收IP:192.168.1.2发送的数据
        recvfrom(Socket_1, recvData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr_1, &ClientAddr_1_Len);
        strcpy(sendData, recvData);
        //转发数据给IP:192.168.1.6
        if((Ret = sendto(Socket_2, sendData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr_2, ClientAddr_2_Len)) < 0)
            printf("发送失败!
");

        //接收IP:192.168.1.6发送的数据
        recvfrom(Socket_2, recvData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr_2, &ClientAddr_2_Len);
        strcpy(sendData, recvData);
        //转发数据给IP:192.168.1.2
        if((Ret = sendto(Socket_1, sendData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr_1, ClientAddr_1_Len)) < 0)
            printf("发送失败!
");
    }
    closesocket(Socket_1);
    closesocket(Socket_2);

    //应用程序完成对接的处理后,调用WSACleanup
    if(WSACleanup() == SOCKET_ERROR)
    {
        printf("WSACLEANUP_ERROR: %d
", WSAGetLastError());
        exit(1);
    }

    system("pause");
    return 0;
}

  但会有个小问题,首先发送数据的客户端的数据无法接收,而且要运行成功必须先发送一个信息,再打开第二个客户端(步骤貌似是这样,前段时间写的了,忘记了...= =)

  客户端1代码:

/**
 *  UDP/IP 客户端 Client.c
 */
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define true 1
#define false 0

#define BUFFSIZE 1024

int main(int argc, char**argv)
{
    int             Ret;
    WSADATA         wsaData;
    SOCKET          SendSocket;
    SOCKADDR_IN     ClientAddr;
    int             ClientAddrLen = sizeof(ClientAddr);
    unsigned short  Port = 5150;
    char            sendData[BUFFSIZE];
    char            recvData[BUFFSIZE];
    time_t          rawtime;

    if((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
    {
        printf("WSASTARTUP_ERROR: %d
", Ret);
        exit(1);
    }

    if((SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
        printf("SendSOCKET_ERROR
");
        exit(1);
    }

    ClientAddr.sin_family = AF_INET;
    ClientAddr.sin_port = htons(Port);
    ClientAddr.sin_addr.S_un.S_addr = inet_addr("192.168.1.2");//本机IPv4地址

    printf("连接到IP:%s 端口:%d
", inet_ntoa(ClientAddr.sin_addr), ntohs(ClientAddr.sin_port));
    puts("-----开始聊天!-----");
    //这样的循环聊天算法硬生生的把UDP协议弄得和前面TCP协议的聊天程序一样了。。。
    //感觉并不太能表现UDP和TCP的区别。。。但我暂时没有好办法
    while(true)
    {
        //发送数据
        printf("
C.C.:");
        scanf("%s", sendData);
        strcat(sendData, "	____");
        time(&rawtime);
        strcat(sendData, ctime(&rawtime));
        if((Ret = sendto(SendSocket, sendData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr, ClientAddrLen)) < 0)
            printf("发送失败!
");

        //接收数据
        if((Ret = recvfrom(SendSocket, recvData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr, &ClientAddrLen)) >= 0)
            printf("鲁鲁:%s
", recvData);
        else
            printf("接收失败!
");
    }
    closesocket(SendSocket);

    if(WSACleanup() == SOCKET_ERROR)
    {
        printf("WSACLEANUP_ERROR: %d
", WSAGetLastError());
        exit(1);
    }

    system("pause");
    return 0;
}

  按照思路即可编写客户端2的代码,代码也基本一样,就是端口号不能一样,需要对应服务端给定的另外一个端口号:

/**
 *  UDP/IP 客户端 Client.c
 */
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define true 1
#define false 0

#define BUFFSIZE 1024

int main(int argc, char**argv)
{
    int             Ret;
    WSADATA         wsaData;
    SOCKET          SendSocket;
    SOCKADDR_IN     ClientAddr;
    int             ClientAddrLen = sizeof(ClientAddr);
    unsigned short  Port = 8888;
    char            sendData[BUFFSIZE];
    char            recvData[BUFFSIZE];
    time_t          rawtime;

    if((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
    {
        printf("WSASTARTUP_ERROR: %d
", Ret);
        exit(1);
    }

    if((SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
        printf("SendSOCKET_ERROR
");
        exit(1);
    }

    ClientAddr.sin_family = AF_INET;
    ClientAddr.sin_port = htons(Port);
    ClientAddr.sin_addr.S_un.S_addr = inet_addr("192.168.1.2");/** 服务端程序的计算机的IPv4地址 */

    printf("连接到IP:%s 端口:%d
", inet_ntoa(ClientAddr.sin_addr), ntohs(ClientAddr.sin_port));
    puts("-----开始聊天!-----");
    while(true)
    {
        //接收数据
        if((Ret = recvfrom(SendSocket, recvData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr, &ClientAddrLen)) >= 0)
            printf("C.C.:%s
", recvData);
        else
            printf("接收失败!
");

        //发送数据
        printf("
鲁鲁:");
        scanf("%s", sendData);
        strcat(sendData, "	____");
        time(&rawtime);
        strcat(sendData, ctime(&rawtime));
        if((Ret = sendto(SendSocket, sendData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr, ClientAddrLen)) < 0)
            printf("发送失败!
");

    }
    closesocket(SendSocket);

    if(WSACleanup() == SOCKET_ERROR)
    {
        printf("WSACLEANUP_ERROR: %d
", WSAGetLastError());
        exit(1);
    }

    system("pause");
    return 0;
}
原文地址:https://www.cnblogs.com/darkchii/p/7954068.html