Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >基于udp的socket编程 c语言_C语言编程游戏

基于udp的socket编程 c语言_C语言编程游戏

作者头像
全栈程序员站长
发布于 2022-10-04 13:02:51
发布于 2022-10-04 13:02:51
20K00
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是你们的朋友全栈君。

1、UDP网络编程主要流程

UDP协议的程序设计框架,客户端和服务器之间的差别在于服务器必须使用bind()函数来绑定侦听的本地UDP端口,而客户端则可以不进行绑定,直接发送到服务器地址的某个端口地址。框图如图1.3所示

UDP协议的服务器端流程

服务器流程主要分为下述6个部分,即建立套接字、设置套接字地址参数、进行端口绑定、接收数据、发送数据、关闭套接字等。

(1)建立套接字文件描述符,使用函数socket(),生成套接字文件描述符。

(2)设置服务器地址和侦听端口,初始化要绑定的网络地址结构。

(3)绑定侦听端口,使用bind()函数,将套接字文件描述符和一个地址类型变量进行绑定。

(4)接收客户端的数据,使用recvfrom()函数接收客户端的网络数据。

(5)向客户端发送数据,使用sendto()函数向服务器主机发送数据。

(6)关闭套接字,使用close()函数释放资源。UDP协议的客户端流程

UDP协议的客户端流程

UDP协议的客户端流程分为套接字建立、设置目的地址和端口、向服务器发送数据、从服务器接收数据、关闭套接字等5个部分。流程如下:

(1)建立套接字文件描述符,socket();

(2)设置服务器地址和端口,struct sockaddr;

(3)向服务器发送数据,sendto();

(4)接收服务器的数据,recvfrom();

(5)关闭套接字,close()。

图1.3 UDP编程流程

2、相关函数

(1) int socket(AF_INET, SOCK_DGRAM, 0);

创建udp socket,返回套接字描述符,UDP协议建立套接字的方式同TCP方式一样,使用socket()函数,只不过协议的类型使用SOCK_DGRAM,而不是SOCK_STREAM。

(2) int sendto(int sockfd, const void *data, int data_len, unsigned int flags, struct sockaddr *remaddr,sock_lenremaddr_len)

功能:基于UDP发送数据报,返回实际发送的数据长度,出错时返回-1

参数说明:

sockfd:套接字描述符

data:指向要发送数据的指针

data_len:数据长度

flags:通常为0

remaddr:远端地址:IP地址和端口号

remaddr_len:地址长度

(3) int recvfrom(int sockfd, void *buf,int buf_len,unsigned int flags,struct sockaddr *from,sock_len *fromlen);

功能:从UDP接收数据,返回实际接收的字节数,失败时返回-1

参数说明:

Sockfd:套接字描述符

buf:指向内存块的指针

buf_len:内存块大小,以字节为单位

flags:一般为0

from:远端的地址,IP地址和端口号

fromlen:远端地址长度

(4) ssize_t recv(int s, void*buf,size_t len, int flags);

连接的UDP可调用recv从服务器读取数据。

ssize_tsend(int s, const void*buf, size_t len, int flags);

连接的UDP可调用send向服务器发送数据。

3、UDPSocket客户服务器通信实例

下面依照通信流程,我们来实现一个UDP回射客户/服务器。

图1.4 UDP回射客户/服务器流程

服务器代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<errno.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<string.h>#define MYPORT 8887#define ERR_EXIT(m) \    do { \    perror(m); \    exit(EXIT_FAILURE); \    } while (0)void echo_ser(int sock){    char recvbuf[1024] = {0};    struct sockaddr_in peeraddr;    socklen_t peerlen;    int n;        while (1)    {                peerlen = sizeof(peeraddr);        memset(recvbuf, 0, sizeof(recvbuf));        n = recvfrom(sock, recvbuf, sizeof(recvbuf), 0,                     (struct sockaddr *)&peeraddr, &peerlen);        if (n <= 0)        {                        if (errno == EINTR)                continue;                        ERR_EXIT("recvfrom error");        }        else if(n > 0)        {            printf("接收到的数据:%s\n",recvbuf);            sendto(sock, recvbuf, n, 0,                   (struct sockaddr *)&peeraddr, peerlen);            printf("回送的数据:%s\n",recvbuf);        }    }    close(sock);}int main(void){    int sock;    if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)        ERR_EXIT("socket error");        struct sockaddr_in servaddr;    memset(&servaddr, 0, sizeof(servaddr));    servaddr.sin_family = AF_INET;    servaddr.sin_port = htons(MYPORT);    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);        printf("监听%d端口\n",MYPORT);    if (bind(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)        ERR_EXIT("bind error");        echo_ser(sock);        return 0;}

客户端代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#define MYPORT 8887char* SERVERIP = "127.0.0.1";#define ERR_EXIT(m) \    do \{ \    perror(m); \    exit(EXIT_FAILURE); \    } while(0)void echo_cli(int sock){    struct sockaddr_in servaddr;    memset(&servaddr, 0, sizeof(servaddr));    servaddr.sin_family = AF_INET;    servaddr.sin_port = htons(MYPORT);    servaddr.sin_addr.s_addr = inet_addr(SERVERIP);        int ret;    char sendbuf[1024] = {0};    char recvbuf[1024] = {0};    while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)    {                printf("向服务器发送:%s\n",sendbuf);        sendto(sock, sendbuf, strlen(sendbuf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));                ret = recvfrom(sock, recvbuf, sizeof(recvbuf), 0, NULL, NULL);        if (ret == -1)        {            if (errno == EINTR)                continue;            ERR_EXIT("recvfrom");        }        printf("从服务器接收:%s\n",recvbuf);                memset(sendbuf, 0, sizeof(sendbuf));        memset(recvbuf, 0, sizeof(recvbuf));    }        close(sock);        }int main(void){    int sock;    if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)        ERR_EXIT("socket");        echo_cli(sock);        return 0;}

实验结果:

UDP编程注意:

1、UDP报文可能会丢失、重复

2、UDP报文可能会乱序

3、UDP缺乏流量控制

4、UDP协议数据报文截断

5、recvfrom返回0,不代表连接关闭,因为udp是无连接的。

6、ICMP异步错误

7、UDP connect

8、UDP外出接口的确定

9、太大的UDP包可能出现的问题

由于UDP不需要维护连接,程序逻辑简单了很多,但是UDP协议是不可靠的,实际上有很多保证通讯可靠性的机制需要在应用层实现,即123点所提到的。比如 如果发送端速度较快,而接收端较慢,很可能会产生 ICMPSource Quench Error,丢弃一些数据包。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/196009.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年9月8日 上,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
linux网络编程之socket(九):使用select函数改进客户端/服务器端程序
一、当我们使用单进程单连接且使用readline修改后的客户端程序,去连接使用readline修改后的服务器端程序,会出现一个有趣的现象,先来看输出: 先运行服务器端,再运行客户端, simba@ub
s1mba
2017/12/28
3.9K0
linux网络编程之socket(九):使用select函数改进客户端/服务器端程序
Socket编程实践(3) 多连接服务器实现与简单P2P聊天程序例程
SO_REUSEADDR选项 在上一篇文章的最后我们贴出了一个简单的C/S通信的例程。在该例程序中,使用"Ctrl+c"结束通信后,服务器是无法立即重启的,如果尝试重启服务器,将被告知: bind: Address already in use 原因在于服务器重新启动时需要绑定地址: bind (listenfd , (struct sockaddr*)&servaddr, sizeof(servaddr)); 而这个时候网络正处于TIME_WAIT的状态,只有在TIME_WAIT状态退出后,套接字被
Tencent JCoder
2018/07/02
6680
windows 下最小化 tcp/udp 实例
实际 windows 下 socket 编程和 linux 下几乎没有什么区别,函数名、结构体信息等都一模一样的,因为这些并非是操作系统所设计决定的。而是由公共的组织在维护和约定这些规范。在 windows 下唯一与 linux 不同的就是需要自己手动加载套接字库。其他几乎完全一致,参考以下代码。
我与梦想有个约会
2023/10/20
2670
Socket编程实践(2) Socket API 与 简单例程
在本篇文章中,先介绍一下Socket编程的一些API,然后利用这些API实现一个客户端-服务器模型的一个简单通信例程。该例子中,服务器接收到客户端的信息后,将信息重新发送给客户端。 socket()函数 socket()函数用于创建一个套接字。这就好像购买了一个电话。不过该电话还没有分配号码。 #include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol
Tencent JCoder
2018/07/02
8930
eBCC性能分析最佳实践(2) - 一个简单的eBCC分析网络函数的latency
http://koji.aliyun-inc.com/kojifiles/packages/ebcc/1.0.0/3.1.al7/src/ebcc-1.0.0-3.1.al7.src.rpm 祝大家五一快乐!
Linux阅码场
2019/06/04
7950
socket网络编程(一)——初识socket
出现一项技术,首先我们弄懂一下,为什么要出现。那么为什么要出现socket这玩意呢?可以很简单的用一句话来概括:
一点sir
2024/01/10
4200
socket网络编程(一)——初识socket
【网络编程】简单的服务端客户端实现
有些图片来源——https://blog.csdn.net/TT_love9527
半生瓜的blog
2023/05/13
4350
【网络编程】简单的服务端客户端实现
linux网络编程之socket(十二):select函数的并发限制和 poll 函数应用举例
一、用select实现的并发服务器,能达到的并发数,受两方面限制 1、一个进程能打开的最大文件描述符限制。这可以通过调整内核参数。可以通过ulimit -n来调整或者使用setrlimit函数设置, 
s1mba
2017/12/28
2K0
linux网络编程之socket(十二):select函数的并发限制和 poll 函数应用举例
linux网络编程之socket(四):使用fork并发处理多个client的请求和对等通信p2p
s1mba
2017/12/28
3.1K0
【计算机网络】socket编程
如:你在淘宝上买了一件衣服,卖家发货后,从广东省发货 到 你所在的地区 ,最终包裹成功到达你的手上,你还需要决定这个快递该怎么用
lovevivi
2023/10/25
3460
【计算机网络】socket编程
linux网络编程之socket(十三):epoll 系列函数简介、与select、poll 的区别
一、epoll 系列函数简介 #include <sys/epoll.h> int epoll_create(int size); int epoll_create1(int flags); i
s1mba
2017/12/28
2.3K0
linux网络编程之socket(十五):UNIX域套接字编程和socketpair 函数
s1mba
2017/12/28
3.9K0
【Linux网络编程】Socket编程--UDP:实现服务器接收客服端的消息
<font color= black face="楷体" size=3><center>🌈个人主页:南桥几晴秋
南桥
2024/10/24
2360
【Linux网络编程】Socket编程--UDP:实现服务器接收客服端的消息
Udp协议Socket编程
  本次socket编程需要使用到 日志文件,此为具体日志编写过程。以及 线程池,线程池原理比较简单,看注释即可。
用户11029129
2024/11/17
1480
Udp协议Socket编程
Linux客户端网口输入转串口输出
另外,在Linux下的C语言头文件一部分不可以在Windows系统上运行,可能导致一些不便。
嘘、小点声
2020/03/19
13K0
[置顶] linux网络编程之socket(十四):基于UDP协议的网络程序
一、下图是典型的UDP客户端/服务器通讯过程 下面依照通信流程,我们来实现一个UDP回射客户/服务器   #include <sys/types.h>  #include <sys/socket.h
s1mba
2017/12/28
1.9K0
[置顶]
        linux网络编程之socket(十四):基于UDP协议的网络程序
socket网络编程基础
套接字 socket是操作系统内核的一个数据结构,它是网络中节点进行相互通信的门户。网络编程实际上也可以称作套接字编程。
xxpcb
2020/08/04
1K0
socket网络编程基础
【LINUX/UNIX网络编程】之使用SOCKET进行UDP编程
(2)客户可向服务器发送多种指令:DOWNLOAD、UPLOAD、YES、NO、START、END、SHUTDOWN、CONTENT、OKDOWLOAD格式:DOWLOAD [filename]表示从服务器下载filename文件,如果服务器存在该文件,返回YES,否则返回NO;客户接收如果是YES,可发送START表示开始下载,之后,服务器将文件传送给客户,客户接收并保存;UPLOAD格式:UPLOAD [filename]表示向服务器上传filename文件,服务器发送NO表示拒绝接收。服务器发送START表示开始传送,之后向服务器传输文件;END:表示文件传送结束SHUTDOWN:表示通讯结束,双方退出。
马三小伙儿
2018/09/12
8190
【LINUX/UNIX网络编程】之使用SOCKET进行UDP编程
UDP套接口编程
常用的UDP实现的程序:DNS域名系统,NFS网络文件系统,SNMP简单网络管理协议 ssize_t recvfrom(int sockfd,void *buff,size_t nbytes,int flags,struct sockaddr * from,socklen_t *addrlen); ssize_t sendto(int sockfd,void *buff,size_t nbytes,int flags,struct sockaddr * to,socklen_t addrlen); sock
用户1154259
2018/01/17
1K0
【Linux网络编程】Socket编程--UDP(第一弹):实现客户端和服务器互相发送消息
任何一个UDP服务通信中,都需要有一个int sockfd的文件描述符,按照系统编程中所说,这里打印出来的文件描述符应该是3,因为0,1,2已经被占用了。
南桥
2024/10/20
2720
【Linux网络编程】Socket编程--UDP(第一弹):实现客户端和服务器互相发送消息
推荐阅读
相关推荐
linux网络编程之socket(九):使用select函数改进客户端/服务器端程序
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验