zoukankan      html  css  js  c++  java
  • Windows Socket UDP协议(服务器与客户端)

    这是一个经常用到的老掉牙的主题了,为了以后用到方便,所以稍微注释了一下然后放上来,代码是本人修改过的,所以也就选成了“原创”。其实现在做码农的,又有多少基础模块能说大体的代码都是自己搞出来的呢?这个“原创"的界定很难!好了,废话不多说,贴代码,基本上用VS的拷过去也是能直接运行的。

    服务器普通实现代码

    <span style="color:#3366ff;">#include <stdio.h> 
    #include <Winsock2.h> 
    
    #pragma comment(lib,"Ws2_32.lib")//连接Sockets相关库
    
    void main()
    {
    	SOCKET socket1;
    	WSADATA wsaData;
    	if (WSAStartup(MAKEWORD(2, 1), &wsaData)) //初始化
    	{
    		printf("Winsock无法初始化!
    ");
    		WSACleanup();
    		return;
    	}
    	printf("服务器开始创建SOCKET。
    ");
    	struct sockaddr_in local;//本机地址相关结构体
    	struct sockaddr_in from;//客户端地址相关结构体
    	int fromlen = sizeof(from);
    	local.sin_family = AF_INET;
    	local.sin_port = htons(27015); ///监听端口 
    	local.sin_addr.s_addr = INADDR_ANY; ///本机 
    	socket1 = socket(AF_INET, SOCK_DGRAM, 0);
    	bind(socket1, (struct sockaddr*)&local, sizeof(local));//绑定SOCKET,此步关键
    	char buffer[1024] = "";
    	if (recvfrom(socket1, buffer, sizeof(buffer), 0, (struct sockaddr*)&from, &fromlen) != SOCKET_ERROR)//阻塞接受客户端的请求
    	{
    		printf("连接成功,开始发送数据
    ");
    	}
    	while (1)
    	{
    		sendto(socket1, buffer, sizeof(buffer), 0, (struct sockaddr*)&from, fromlen);//发数据给客户端,由于是
    		Sleep(200);
    	}
    	closesocket(socket1);
    	WSACleanup();
    }</span>

    客户端普通实现代码

    #include <stdio.h> 
    #include <Winsock2.h> 
    
    #pragma comment(lib,"Ws2_32.lib")//连接Sockets相关库
    
    void main()
    {
    	SOCKET socket1;
    	WSADATA wsaData;
    	if (WSAStartup(MAKEWORD(2, 1), &wsaData)) //初始化
    	{
    		printf("Winsock无法初始化!
    ");
    		WSACleanup();
    		return;
    	}
    	printf("客户端开始创建SOCKET。
    ");
    	struct sockaddr_in server;
    	int len = sizeof(server);
    	server.sin_family = AF_INET;
    	server.sin_port = htons(27015); ///server的监听端口 
    	server.sin_addr.s_addr = inet_addr("127.0.0.1"); ///server的地址 
    	socket1 = socket(AF_INET, SOCK_DGRAM, 0);
    	char buffer[1024] = "haha";
    	if (sendto(socket1, buffer, sizeof(buffer), 0, (struct sockaddr*)&server, len) != SOCKET_ERROR)//发送信息给服务器,发送完进入等待,代表服务器在客户端启动前必须是等待状态
    	{
    		printf("发送请求,等待客户端接受并发送数据
    ");
    	}
    	while (1)
    	{
    		Sleep(100);
    		if (recvfrom(socket1, buffer, sizeof(buffer), 0, (struct sockaddr*)&server, &len) != SOCKET_ERROR)
    		printf("从客户端接收到的数据:%s
    ", buffer);
    	}
    	closesocket(socket1);
    	WSACleanup();
    
    }


    在程序设计中通常希望对于数据交互方有没有数据传来做出反应,而不是单纯的阻塞等待在那里。这个时候可以用select先进行探测,一探测到有数据过来才调用recvfrom,如果超过时间则做出相应的超时处理,实现需要在上面的代码中recvfrom(原程序该函数阻塞)处稍作修改,修改代码如下:

    fd_set readfds;
    FD_ZERO(&readfds);//将指定的文件描述符集清空,在对文件描述符集合进行设置前,必须对其进行初始化,如果不清空,由于在系统分配内存空间后,通常并不作清空处理,所以结果是不可知的
    FD_SET(socket1, &readfds); //用于在文件描述符集合中增加一个新的文件描述符。
    struct timeval tv_out;
    tv_out.tv_sec = 5;//等待5秒
    tv_out.tv_usec = 0;
    int selright=select(socket1 + 1, &readfds, NULL, NULL, &tv_out);
    if (selright<=0)//为0时为超时,小于0时为错误,这两种情况皆非我们所想,故做出相同的处理
    {
    	printf("连接失败");
    	return;
    }
    else
    {
    	if (recvfrom(socket1, buffer, sizeof(buffer), 0, (struct sockaddr*)&from, &fromlen) != SOCKET_ERROR)//阻塞接受客户端的请求
    	{
    		printf("连接成功,开始发送数据
    ");
    	}
    }
    当然如果希望循环等待,则每次都必须重新设置readfds



  • 相关阅读:
    正面管教读书笔记 05 当心逻辑后果
    正面管教读书笔记 04 重新看待不良行为
    正面管教读书笔记 03 出生顺序的重要性
    正面管教读书笔记 02 几个基本概念
    正面管教读书笔记 01 正面的方法
    Shiro身份认证异常:Authentication failed for token submission
    springboot项目配置类使用@ConfigurationProperties注解时,提示Spring Boot Configuration Annotation Proessor not found in classpath
    mysql的性能优化简介
    mysql的逻辑架构
    CentOS7环境下yum方式安装MySQL5.7
  • 原文地址:https://www.cnblogs.com/weixinhum/p/3916675.html
Copyright © 2011-2022 走看看