坚持在代码中注释,边读代码边学习Linux网络编程

使用到的发送函数原型:

       #include <sys/types.h>#include <sys/socket.h>ssize_t send(int sockfd, const void *buf, size_t len, int flags);成功返回发送字节数,出错返回-1ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);成功返回发送字节数,出错返回-1ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);成功返回发送字节数,出错返回-1

使用到的接受函数原型:

       #include <sys/types.h>#include <sys/socket.h>ssize_t recv(int sockfd, void *buf, size_t len, int flags);ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);成功返回消息的字节数,无消息返回0,出错返回-1

设置套接字选项函数和获取套接字选项函数:

       #include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);

编写一个UDP客户端和服务器:

客户端代码:

#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <memory.h>
#include <arpa/inet.h>int main(int argc, char *argv[])
{if(argc < 3){printf("usage: %s ip port \n",argv[0]);exit(1);}/*步骤1: 创建socke套接字*/int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd < 0){perror("socket error!");exit(1);}/**步骤2: 调用recvfrom和sendto等函数和服务器进行双向通信*/struct sockaddr_in serveraddr;memset(&serveraddr, 0, sizeof(serveraddr));serveraddr.sin_family = AF_INET;   //使用IPV4serveraddr.sin_port = htons(atoi(argv[2]));inet_pton(AF_INET, argv[1], &serveraddr.sin_addr.s_addr);char buffer[1024] = "hello iotek";//向服务器发送数据报文if(sendto(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0){perror("sendto error!");exit(1);}else{//若是成功发送客户端就开始接受服务端发送的数据报文memset(buffer, 0, sizeof(buffer));//若是上面已经使用,sendto函数已经发送成功下面可以直接使用recv//否则需要使用recvfrom函数//在使用tcp的时候如果接受的是0 说明对方断开连接,但是udp是面向无连接的不需要判断接受的数据是否等于0//只需要判断是否小于0即可,当接收的数据小于0的时候代表接收出错if(recv(sockfd, buffer, sizeof(buffer), 0) < 0){perror("recv error");exit(1);}else{printf("%s\n",buffer);}}}

服务器代码:

#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <arpa/inet.h>int sockfd;
void do_service(int fd);
void sig_handler(int signo);
void out_addr(struct sockaddr_in *clientaddr);int main(int argc, char * argv[])
{if(argc < 2){printf("usage: %s port\n", argv[0]);exit(1);}if(signal(SIGINT, sig_handler) == SIG_ERR)    //开始捕获信号 SIGINT {perror("signal sigint error!");exit(1);}/*步骤1: 创建socket*/sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd < 0){perror("socket error!");exit(1);}/*设置选项使停掉的端口马上就可以恢复使用*/int ret;int opt = 1;//设置套接字选项if((ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) < 0){perror("setsockopt error!");exit(1);}/*步骤2: 调用bind函数对socket和地址进行绑定*/struct sockaddr_in serveraddr;memset(&serveraddr, 0, sizeof(serveraddr));serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(atoi(argv[1])); //portserveraddr.sin_addr.s_addr = INADDR_ANY;  //ip匹配所有的ipif(bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0){perror("bind error!");exit(1);}/*步骤3: 和客户端进行双向数据通讯*/while(1){do_service(sockfd);}}void do_service(int fd)
{struct sockaddr_in clientaddr;socklen_t len = sizeof(clientaddr);char buffer[1024];memset(buffer, 0, sizeof(buffer));//接受客户端发送过来的数据报文   可以获得对方的地址信息if(recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr*)&clientaddr, &len) < 0){perror("recvfrom error!");}else{out_addr(&clientaddr);printf("client send infomation: %s\n", buffer);//服务器向客户端发送报文long int t = time(0);char *ptr = ctime(&t);size_t size = strlen(ptr) * sizeof(char);if(sendto(fd, ptr, size, 0, (struct sockaddr*)&clientaddr, len) < 0){perror("send error!");}}}
void sig_handler(int signo)
{if(signo == SIGINT){printf("serrver clolse!\n");;close(sockfd);exit(1);}
}//输出客户端信息
void out_addr(struct sockaddr_in *clientaddr)
{char ip[16];int port;memset(ip, 0, sizeof(ip));inet_ntop(AF_INET, &clientaddr->sin_addr.s_addr, ip, sizeof(ip));port = ntohs(clientaddr->sin_port);printf("client : %s(%d)\n", ip, port);}

说明:在客户端中若是不想使用sendto函数,而是使用send函数需要结合connect函数使用:

if(sendto(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0){perror("sendto error!");exit(1);}
等价于if(connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
{perror("connect error!");exit(1);
}+if(send(sockfd, buffer, sizeof(buffer), 0) < 0)
{perror("sendto error!");exit(1);}

但是需要注意的一点就是在udp中使员工connect函数并不像tcp中会进行三次握手,在udp中使用send函数,只是向内核中记录服务器的地址信息和端口等数据信息;即相当于实现相应sockfd描述符与服务器地址的绑定,因此再调用send函数就不需要再次提供服务器地址信息,就能将相应的数据报文正确的发送。

调用connect的好处就是在udp的客户端中能够保证接受的数据是来之连接的服务器的数据报文,否则不使用connect的话,客户端有可能接受不是来之服务器的数据报文

测试:

同样为了测试方便使用环回地址andrew@andrew-Thurley:~/work/network$ bin/time_udp_server 8888
client : 127.0.0.1(45082)
client send infomation: hello iotekandrew@andrew-Thurley:~/work/network$ bin/time_udp_client 127.0.0.1 8888
Sun Aug 19 12:22:21 2018

基于UDP客户端服务器的编程模型-linux网络编程相关推荐

  1. linux网络编程 ppt,LINUX网络编程.ppt

    <LINUX网络编程.ppt>由会员分享,可在线阅读,更多相关<LINUX网络编程.ppt(47页珍藏版)>请在人人文库网上搜索. 1.LINUX网络编程,行业事业部 黄文举 ...

  2. linux 网络编程 ping,Linux 网络编程基础(4) -- Ping 的C代码实现

    1.背景 在进行网络编程的时候,通常使用的协议有TCP协议,UDP协议.这些协议在简历套接字之初需要制定套接字的类型,比如TCP应当设置为 SOCK_STREAM, UDP对应的套接字应当设置为SOC ...

  3. linux环境编程unp,Linux网络编程(1):如何使用unp.h

    俗话说万事开头难,学习新知识也是如此,当我们下定决心要实现UNP中的例子时,发现却无法将程序部署上去,这种感觉是不是很令人沮丧?本文就是用来给我自己这种linux菜鸟扫盲用的. 首先,UNP的源码链接 ...

  4. 网络编程模型及网络编程三要素

    网络模型 计算机网络之间以何种规则进行通信,就是网络模型研究问题. 网络模型一般是指 OSI(Open SystemInterconnection开放系统互连)参考模型 TCP/IP参考模型 网络模型 ...

  5. linux网络编程socket,Linux网络编程入门

    socket又叫做套接字,网络编程又叫做套接字编程.而socket地址也称为套接字地址,可以理解为计算机的网络地址. 1.理解socket地址 假设小明同学想给女神打电话需要知道对方的电话号码才能继续 ...

  6. linux环境编程unp,linux网络编程之怎么配置好unp.h文件

    1.获取unp源码 然后用tar -zxvf unpv13e.tar.gz命令解压 2.进入unpv13e目录执行configure cd unpv13e ,然后执configure文件 3.打开RE ...

  7. linux 网络7层模型,Linux网络编程——OSI七层模型、TCP/IP模型

    OSI七层模型 开放式系统互连(Open System Interconnect),模型分为7层,从下往上依次为: 物理层: 数据链路层: 网络层: 传输层: 会话层: 表示层: 应用层: 记不住怎么 ...

  8. linux系统网络编程简介,Linux网络编程入门

    本文是在Linux环境下编写网络程序,有必要介绍下实验环境. 1.如右侧环境所示分为两上下两个部分, 上半部分是文件管理,可以进行创建文件.删除文件以及文件中编写程序等. 下半部分是Linux系统命令 ...

  9. Linux 高性能服务器开发笔记:Reactor 模型定时器 | 网络编程定时器

    本文主要根据游双书本 Linux 高性能服务器开发 学习分析 linux 网络编程常用到的定时器模型,配备详细理解和分析,同时分析了 Linux 内核中定时器的低精度时间轮和高精度定时器实现思路还有 ...

最新文章

  1. shell脚本编程之更多结构化命令
  2. Android使用popueWindow自定义Spinner
  3. mysql 密码忘记了怎么办? [仅msyql8版本]
  4. archlinux php mysql,arch linux上安装 httpd+php+mysql+ openssl(转)
  5. [译]如何成为一个优秀的前端工程师
  6. MyBatis工作流程及配置
  7. 油田生产数据选取进展22.2.11——2.17——2.26
  8. ERROR in ./src/vue/login.vue?vuetype=templateid=28b333d2 2:0 Module parse failed: Unexpected toke
  9. 数字图像处理-高反差保留算法
  10. 黑猴子的家:Minimal Install VS Server with GUI VS GNOME Desktop
  11. RNA-Seq质控工具RseQC安装使用
  12. 42、在建工程的施工单位应开展的消防安全教育工作
  13. C++primer十万字笔记 第九章 顺序容器
  14. hcip第一天复习笔记
  15. Lasso-Logistic回归-R语言应用详解
  16. Nginx安装配置(lua全模块、GEOIP、加入系统服务)---无坑安装
  17. 马自达化身杠精?老子就是不用触摸屏!
  18. 兰州大学计算机专业张教授,兰州大学信息科学与工程学院
  19. 利用CCA进行故障检测
  20. web前端工程师怎么写月报_Web开发人员月报2018年9月

热门文章

  1. 【蓝桥杯】算法提高 7-2求arccos值
  2. java IO(输入输出) 对象的序列化和反序列化
  3. hdu-3625 Examining the Rooms(斯特灵数第一类)
  4. hdu-4510 小Q系列故事——为什么时光不能倒流(比赛被虐的一道水题)
  5. NYOJ 170 网络的可靠性
  6. hdu 4160 Dolls 匈牙利算法求最大匹配
  7. zigbee之SampleApp_ProcessEvent()
  8. Oracle建立约束、删除约束
  9. 2017-2018-2 20155228 《网络对抗技术》 实验四:恶意代码分析
  10. Atitit 发帖机系列(7) 词法分析的方法attilax大总结)