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\n", Ret);
        exit(1);
    }

    if((Socket_1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
        printf("Socket_1_ERROR\n");
        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\n", SOCKET_ERROR);
        exit(1);
    }

    if((Socket_2 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
        printf("Socket_2_ERROR\n");
        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\n", 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("发送失败!\n");

        //接收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("发送失败!\n");
    }
    closesocket(Socket_1);
    closesocket(Socket_2);

    //应用程序完成对接的处理后,调用WSACleanup
    if(WSACleanup() == SOCKET_ERROR)
    {
        printf("WSACLEANUP_ERROR: %d\n", 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\n", Ret);
        exit(1);
    }

    if((SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
        printf("SendSOCKET_ERROR\n");
        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\n", inet_ntoa(ClientAddr.sin_addr), ntohs(ClientAddr.sin_port));
    puts("-----开始聊天!-----");
    //这样的循环聊天算法硬生生的把UDP协议弄得和前面TCP协议的聊天程序一样了。。。
    //感觉并不太能表现UDP和TCP的区别。。。但我暂时没有好办法
    while(true)
    {
        //发送数据
        printf("\nC.C.:");
        scanf("%s", sendData);
        strcat(sendData, "\t____");
        time(&rawtime);
        strcat(sendData, ctime(&rawtime));
        if((Ret = sendto(SendSocket, sendData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr, ClientAddrLen)) < 0)
            printf("发送失败!\n");

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

    if(WSACleanup() == SOCKET_ERROR)
    {
        printf("WSACLEANUP_ERROR: %d\n", 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\n", Ret);
        exit(1);
    }

    if((SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
        printf("SendSOCKET_ERROR\n");
        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\n", 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\n", recvData);
        else
            printf("接收失败!\n");

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

    }
    closesocket(SendSocket);

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

    system("pause");
    return 0;
}

原文地址:https://www.cnblogs.com/darkchii/p/7954068.html

时间: 2024-08-24 23:36:57

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

UNP(一):网络编程角度下的TCP、UDP协议

此博文是学习UNP(UNIX Network Programming)后的读书笔记,供以后自己翻阅回顾知识. TCP.UDP概述 在前面<计算机网络与TCP/IP>栏目下已经介绍过一些关于TCP.UDP的相关知识TCP/IP(三):传输层TCP与UDP,这里只是简单从UNIX网络编程的角度介绍TCP.UDP协议. 我们都知道UDP 缺乏可靠性.无连接的,面向数据报 的协议,如果想确保数据报到达目的地,必须自己在应用层实现一些特性:对端的确定.本端的超时和重传等.UDP面向报文的特性,使得UDP

Windows网络编程

第一章 序言 我写这个专题的目的,一方面是为了通过对网络编程再一次系统的总结,提高自己的网络编程水平,特别是Windows下的网络编程水平.同一时候,我也希望,能为众多初学网络编程的人提供一点帮助,由于我開始学习网络编程的时候,能找到的资料就非常少.当然,花钱能够买到翻译版本号的书:) 首先向大家推荐一本非常好的參考书,Network Programming for Microsoft Windows 2nd, 初学网络编程的时候我还不知道有这样一本好书,仅仅是上各大论坛把能找到的网络编程方面的

Windows网络编程经验小结

转自:CSDN网友的强贴,其ID:gdy119 (夜风微凉) 1. 如果在已经处于 ESTABLISHED状态下的socket(一般由端口号和标志符区分)调用closesocket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket: BOOL bReuseaddr=TRUE; setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL)); 2. 如果要已经处于连接状态的soket

Windows网络编程 2 【转】

Windows网络编程使用winsock.Winsock是一个基于Socket模型的API,在Windows系统中广泛使用.使用Winsock进行网络编程需要包含头文件Winsock2.h,需要使用库ws2_32.lib,包含方法:可以使用语句来告诉编译器连接该库#pragma comment(lib, “ws2_32.lib”);如果使用VS,可以通过“项目” --> “XX属性”--> “连接器”-->“输入”--> “附加依赖项”添加ws2_32.lib. (XX为当前工程名

Winsock网络编程笔记(3)----基于UDP的server和client

在上一篇随笔中,对Winsock中基于tcp面向连接的Server和Client通信进行了说明,但是,Winsock中,Server和Client间还可以通过无连接通信,也就是采用UDP协议.. 因此,这一篇随笔也简单的列举基于UDP的Server和Client的实现.. 和基于TCP的实现相比,其主要的不同点包括: ①接收端(简单地说就是服务器)/发送端(简单地说就是客户端)在创建Socket时候,参数要选择SOCK_DGRAM, IPPROTO_UDP: ②接收端不需要调用listen和ac

关于网络编程中MTU、TCP、UDP、IP

名词解释: MTU(Maxium Transmission Unit)最大传输单元 TCP (Transmission Control Protocal)传输控制协议 UDP (Usage Datagram Protocal)用户数据报协议 IP (Internet Protocal) 因特网协议 TCP/IP协议,涉及到四层:链路层,网络层,传输层,应用层(TCP/IP是一个协议簇,并不是代表TCP协议和IP协议) 以太网(Ethemet)的数据帧在链路层 IP包在网络层 TCP或UDP包在传

windows网络编程的一些理论

参考自<VC++深入详解> 这是我在看书时记录下来的东西. 注:下面的Socket其实都应该是socket 第14章网络编程 Socket是连接应用程序与网络驱动程序的桥梁,Socket在应用程序中创建,通过绑定与驱动程序建立关系. 此后,应用程序给Socket的数据,由Socket交给驱动程序向网络上发送出去. 计算机从网络上收到与该Socket绑定的IP地址和端口号相关的数据后,由驱动程序交给Socket,应用程序便可从该Socket中提取接收到的数据. 14.1 计算机网络基本知识. 1

72&gt;&gt;Windows 网络编程

1 网络编程 API 2 3 4 int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData ); lpWSAData 是一个返回值:成功返回 0,失败返回 -1,错误代码 WSASYSNOTREADY 表示基础网络子系统没有准备好网络通行,WSAVERNOTSUPPORTED 表示 Socket 版本不支持,WSAEINPROGRESS 表示一个阻塞的 Sockets 操作在进程中,WSAEPROCLIM 表示 Sockets 支持的

windows 网络编程[转]

利用winsock编写网络应用程序服务端的步骤简述如下WSAStartup 初始化网络编程库 socket 创建套接字 bind 指定地址.端口,绑定套接字 listen 进入监听状态 accept 等待接收新连接 send/recv 收发数据 closesocket 关键套接字 WSAStartup 释放对动态库的使用 下面详细介绍各API 1. Winsock初始化 调用int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData