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

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

  服务端代码:

  1. /**
  2. * UDP/IP 服务器端 Server.c
  3. */
  4. #include <winsock2.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <time.h>
  8.  
  9. #define true 1
  10. #define false 0
  11.  
  12. #define BUFFSIZE 1024
  13.  
  14. int main(int argc, char**argv)
  15. {
  16. int Ret;
  17. WSADATA wsaData;
  18. SOCKET Socket_1;
  19. SOCKET Socket_2;
  20. SOCKADDR_IN ClientAddr_1;
  21. int ClientAddr_1_Len = sizeof(ClientAddr_1);
  22. SOCKADDR_IN ClientAddr_2;
  23. int ClientAddr_2_Len = sizeof(ClientAddr_2);
  24. unsigned short Port_1 = 5150;
  25. unsigned short Port_2 = 8888;
  26. char sendData[BUFFSIZE];
  27. char recvData[BUFFSIZE];
  28.  
  29. if((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
  30. {
  31. printf("WSASTARTUP_ERROR: %d\n", Ret);
  32. exit(1);
  33. }
  34.  
  35. if((Socket_1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
  36. printf("Socket_1_ERROR\n");
  37. exit(1);
  38. }
  39. //将端口变量从主机字节顺序转换位网络字节顺序
  40. ClientAddr_1.sin_family = AF_INET;
  41. ClientAddr_1.sin_port = htons(Port_1);
  42. ClientAddr_1.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
  43.  
  44. //使用bind将这个地址信息和套接字绑定起来
  45. if(bind(Socket_1, (SOCKADDR *)&ClientAddr_1, ClientAddr_1_Len) == SOCKET_ERROR)
  46. {
  47. printf("BIND_SOCKET_1_ERROR: %d\n", SOCKET_ERROR);
  48. exit(1);
  49. }
  50.  
  51. if((Socket_2 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
  52. printf("Socket_2_ERROR\n");
  53. exit(1);
  54. }
  55. //将端口变量从主机字节顺序转换位网络字节顺序
  56. ClientAddr_2.sin_family = AF_INET;
  57. ClientAddr_2.sin_port = htons(Port_2);
  58. ClientAddr_2.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
  59.  
  60. //使用bind将这个地址信息和套接字绑定起来
  61. if(bind(Socket_2, (SOCKADDR *)&ClientAddr_2, ClientAddr_2_Len) == SOCKET_ERROR)
  62. {
  63. printf("BIND_SOCKET_2_ERROR: %d\n", SOCKET_ERROR);
  64. exit(1);
  65. }
  66.  
  67. printf("建立连接成功!");
  68.  
  69. //服务器作为中转站
  70. //为两个IP之间互相转发消息
  71. while(true)
  72. {
  73. //接收IP:192.168.1.2发送的数据
  74. recvfrom(Socket_1, recvData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr_1, &ClientAddr_1_Len);
  75. strcpy(sendData, recvData);
  76. //转发数据给IP:192.168.1.6
  77. if((Ret = sendto(Socket_2, sendData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr_2, ClientAddr_2_Len)) < 0)
  78. printf("发送失败!\n");
  79.  
  80. //接收IP:192.168.1.6发送的数据
  81. recvfrom(Socket_2, recvData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr_2, &ClientAddr_2_Len);
  82. strcpy(sendData, recvData);
  83. //转发数据给IP:192.168.1.2
  84. if((Ret = sendto(Socket_1, sendData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr_1, ClientAddr_1_Len)) < 0)
  85. printf("发送失败!\n");
  86. }
  87. closesocket(Socket_1);
  88. closesocket(Socket_2);
  89.  
  90. //应用程序完成对接的处理后,调用WSACleanup
  91. if(WSACleanup() == SOCKET_ERROR)
  92. {
  93. printf("WSACLEANUP_ERROR: %d\n", WSAGetLastError());
  94. exit(1);
  95. }
  96.  
  97. system("pause");
  98. return 0;
  99. }

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

  客户端1代码:

  1. /**
  2. * UDP/IP 客户端 Client.c
  3. */
  4. #include <winsock2.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <time.h>
  9.  
  10. #define true 1
  11. #define false 0
  12.  
  13. #define BUFFSIZE 1024
  14.  
  15. int main(int argc, char**argv)
  16. {
  17. int Ret;
  18. WSADATA wsaData;
  19. SOCKET SendSocket;
  20. SOCKADDR_IN ClientAddr;
  21. int ClientAddrLen = sizeof(ClientAddr);
  22. unsigned short Port = 5150;
  23. char sendData[BUFFSIZE];
  24. char recvData[BUFFSIZE];
  25. time_t rawtime;
  26.  
  27. if((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
  28. {
  29. printf("WSASTARTUP_ERROR: %d\n", Ret);
  30. exit(1);
  31. }
  32.  
  33. if((SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
  34. printf("SendSOCKET_ERROR\n");
  35. exit(1);
  36. }
  37.  
  38. ClientAddr.sin_family = AF_INET;
  39. ClientAddr.sin_port = htons(Port);
  40. ClientAddr.sin_addr.S_un.S_addr = inet_addr("192.168.1.2");//本机IPv4地址
  41.  
  42. printf("连接到IP:%s 端口:%d\n", inet_ntoa(ClientAddr.sin_addr), ntohs(ClientAddr.sin_port));
  43. puts("-----开始聊天!-----");
  44. //这样的循环聊天算法硬生生的把UDP协议弄得和前面TCP协议的聊天程序一样了。。。
  45. //感觉并不太能表现UDP和TCP的区别。。。但我暂时没有好办法
  46. while(true)
  47. {
  48. //发送数据
  49. printf("\nC.C.:");
  50. scanf("%s", sendData);
  51. strcat(sendData, "\t____");
  52. time(&rawtime);
  53. strcat(sendData, ctime(&rawtime));
  54. if((Ret = sendto(SendSocket, sendData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr, ClientAddrLen)) < 0)
  55. printf("发送失败!\n");
  56.  
  57. //接收数据
  58. if((Ret = recvfrom(SendSocket, recvData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr, &ClientAddrLen)) >= 0)
  59. printf("鲁鲁:%s\n", recvData);
  60. else
  61. printf("接收失败!\n");
  62. }
  63. closesocket(SendSocket);
  64.  
  65. if(WSACleanup() == SOCKET_ERROR)
  66. {
  67. printf("WSACLEANUP_ERROR: %d\n", WSAGetLastError());
  68. exit(1);
  69. }
  70.  
  71. system("pause");
  72. return 0;
  73. }

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

  1. /**
  2. * UDP/IP 客户端 Client.c
  3. */
  4. #include <winsock2.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <time.h>
  9.  
  10. #define true 1
  11. #define false 0
  12.  
  13. #define BUFFSIZE 1024
  14.  
  15. int main(int argc, char**argv)
  16. {
  17. int Ret;
  18. WSADATA wsaData;
  19. SOCKET SendSocket;
  20. SOCKADDR_IN ClientAddr;
  21. int ClientAddrLen = sizeof(ClientAddr);
  22. unsigned short Port = 8888;
  23. char sendData[BUFFSIZE];
  24. char recvData[BUFFSIZE];
  25. time_t rawtime;
  26.  
  27. if((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0)
  28. {
  29. printf("WSASTARTUP_ERROR: %d\n", Ret);
  30. exit(1);
  31. }
  32.  
  33. if((SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
  34. printf("SendSOCKET_ERROR\n");
  35. exit(1);
  36. }
  37.  
  38. ClientAddr.sin_family = AF_INET;
  39. ClientAddr.sin_port = htons(Port);
  40. ClientAddr.sin_addr.S_un.S_addr = inet_addr("192.168.1.2");/** 服务端程序的计算机的IPv4地址 */
  41.  
  42. printf("连接到IP:%s 端口:%d\n", inet_ntoa(ClientAddr.sin_addr), ntohs(ClientAddr.sin_port));
  43. puts("-----开始聊天!-----");
  44. while(true)
  45. {
  46. //接收数据
  47. if((Ret = recvfrom(SendSocket, recvData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr, &ClientAddrLen)) >= 0)
  48. printf("C.C.:%s\n", recvData);
  49. else
  50. printf("接收失败!\n");
  51.  
  52. //发送数据
  53. printf("\n鲁鲁:");
  54. scanf("%s", sendData);
  55. strcat(sendData, "\t____");
  56. time(&rawtime);
  57. strcat(sendData, ctime(&rawtime));
  58. if((Ret = sendto(SendSocket, sendData, BUFFSIZE, 0, (SOCKADDR*)&ClientAddr, ClientAddrLen)) < 0)
  59. printf("发送失败!\n");
  60.  
  61. }
  62. closesocket(SendSocket);
  63.  
  64. if(WSACleanup() == SOCKET_ERROR)
  65. {
  66. printf("WSACLEANUP_ERROR: %d\n", WSAGetLastError());
  67. exit(1);
  68. }
  69.  
  70. system("pause");
  71. return 0;
  72. }

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

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

    TCP/IP协议(面向连接协议)类似于打电话时,对方一定在手机附近并且此刻都在和对方进行通话.一定保证双方都在线,才能进行数据传输.UDP/IP协议(无连接协议)就像邮箱,不保证对方一定在等你邮件且对 ...

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

    此博文是学习UNP(UNIX Network Programming)后的读书笔记,供以后自己翻阅回想知识. TCP.UDP概述 在前面<计算机网络与TCP/IP>栏目下已经介绍过一些关于 ...

  3. (网络编程)基于tcp(粘包问题) udp协议的套接字通信

    import   socket 1.通信套接字(1人1句)服务端和1个客户端 2.通信循环(1人多句)服务端和1个客户端 3.通信循环(多人(串行)多句)多个客户端(服务端服务死:1个客户端---&g ...

  4. {网络编程}和{多线程}应用:基于UDP协议【实现多发送方发送数据到同一个接收者】--练习

    要求: 使用多线程实现多发送方发送数据到同一个接收者 代码: 发送端:可以在多台电脑上启动发送端,同时向接收端发送数据 注意:匹配地址和端口号 package com.qf.demo; import ...

  5. [转]Windows网络编程学习-面向连接的编程方式

    直接附上原文链接:windows 网络编程学习-面向连接的编程方式

  6. Windows网络编程 2 【转】

    Windows网络编程使用winsock.Winsock是一个基于Socket模型的API,在Windows系统中广泛使用.使用Winsock进行网络编程需要包含头文件Winsock2.h,需要使用库 ...

  7. 【Hadoop离线基础总结】zookeeper的介绍以及集群环境搭建、网络编程和RPC的简单了解

    ZooKeeper的介绍以及集群环境搭建.网络编程和RPC的简单了解 ZooKeeper介绍 概述 ZooKeeper是一个分布式协调服务的开源框架,主要用来解决分布式集群中应用系统的一致性问题.例如 ...

  8. 网络编程 套接字socket TCP UDP

    网络编程与套接字 网络编程 网络编程是什么: ​ 网络通常指的是计算机中的互联网,是由多台计算机通过网线或其他媒介相互链接组成的 ​ 编写基于网络的应用程序的过程序称之为网络编程. 网络编程最主要的工 ...

  9. Android网络编程要学的东西与Http协议学习

    本节引言: 本节开始我们来学习Android网络编程相关的一些东西:Android端网络编程是要干嘛?http协议的学习,使用自带扣脚Json解析类解析Json,XML解析常用的几种方式,HttpUr ...

随机推荐

  1. 浅谈hover用法

    在前端页面制作中,我们时常要用到移动显示.隐藏的动态效果,我们一般采用js来实现此效果.不过在大部分情况下,我们也可以使用hover来实现此动态效果. 在此,我谈一谈我对hover的用法,请看以下代码 ...

  2. Arrays类的概述和常用的方法

    1.  2.为了防止外界创造对象,系统把Arrays的无参构造方法设为私有: 并且再其类方法用静态修饰,强制你用类名调用方法,另外math和system也是如此

  3. 【MySQL】数据类型之字符相关

    " 目录 字符类型 char类型 varchar类型 实测 总结 枚举类型与集合类型 字符类型 官网:https://dev.mysql.com/doc/refman/5.7/en/char ...

  4. Tensorflow机器学习入门——常量、变量、placeholder和基本运算

    一.这里列出了tensorflow的一些基本函数,比较全面:https://blog.csdn.net/M_Z_G_Y/article/details/80523834 二.这里是tensortflo ...

  5. C++中宏的定义与用法(现已被内联函数所代替)

    在noip中,宏还是被经常采用,所以这里讲一下,C++中宏的定义与用法 第一种用法——配合条件编译:#define DEBUG 定义一个叫DEBUG的标识符.它应该与#ifdef或#ifndef配合使 ...

  6. spark实验(四)--RDD编程(1)

    一.实验目的 (1)熟悉 Spark 的 RDD 基本操作及键值对操作: (2)熟悉使用 RDD 编程解决实际具体问题的方法. 二.实验平台 操作系统:centos6.4 Spark 版本:1.5.0 ...

  7. powershell 无法运行一些脚本的情况

    有时候在powershell里运行脚本会报错: 无法加载文件 ******.ps1,因为在此系统中禁止执行脚本.有关详细信息,请参阅 "get-help about_signing" ...

  8. Springboot学习:核心配置文件

    核心配置文件介绍 SpringBoot使用一个全局配置文件,配置文件名是固定的 application.properties application.yml 配置文件的作用:修改SpringBoot自 ...

  9. 子元素使用position:fixed,导致他的宽度不能和父元素保持一致的解决方案

    最近在编码过程中,遇到过这样一个问题,代码如下,我们有一个父级,他有一定的宽度,在他的里面有两个子级,其中一个是绝对定位的,且要求他们的宽度都和父级保持一致,然后问题就出现了,我们会发现,有了定位的s ...

  10. 一文解读IBMS (转)

    IBMS系统是面向建筑设备生命周期的管理:面向楼宇的管理者和使用者:是传统BAS系统数据及功能的聚合. 更高效的分析和管理.更复杂的应用:跨平台.跨品牌的整合各子系统数据提供一套采集楼宇设备实时数据的 ...