zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    running Android Studio on Windows 7 fails, no Android SDK found
    Dalvik虚拟机简要介绍和学习计划
    免费HTTP上传文件控件WebUploadFile.ocx发布,让实现Word在线编辑器变得容易
    ASP.NET生成缩略图的代码
    C++ MFC 关于SelectObject,请解释下,谢谢
    Visual C++中MFC消息的分类
    深入思考全局静态存储区、堆区和栈区
    coredump简介与coredump原因总结
    c++函数中的 指针参数跟地址参数区别
    解决SWFUpload在Chrome、Firefox等浏览器下的问题
  • 原文地址:https://www.cnblogs.com/darkchii/p/7954068.html
Copyright © 2011-2022 走看看