网络编程学习笔记(UDP的connect函数)
对于已连接的UDP套接口,发生了三个变化:
1、再也不能给输出操作指定目的IP地址和端口,也就是说,不能再调用 sendto,而使用send或者write。写到已连接UDP套接口上的任何东西都自动发送到由connect指定的协议地址。
2、不用recvfrom,而用recv或者read。在已连接的UDP套接口上由内核为输入操作返回的唯一数据报是来自connect所指定协议地址的数据报。
3、异步错误由已连接UDP套接口返回给进程 。未连接UDP套接口不接收任何异步错误。
给一个UDP套接口多次调用 connect
对于已连接UDP套接口,进程可给那个套接口再次调用 connect达到下面两个目的:
1、指定新的IP地址和端口号
2、断开套接口
第一种情况即给已连接UDP套接口指定新的对方,与TCP套接口中connect的使用有所不同,只可给TCP套接口调用 一次connect
第二种情况,调用 connect,但是设置 套接口地址结构的地址族为AF_UNSPEC。这可能返回一个EAFNOSPPORT错误,但没有关系,使得套接口断开连接的是在已连接UDP套接口上调用 connect的进程。
性能
在未连接UDP套接口上调用 sendto时,内核作的工作是:暂时连接套接口,发送数据报,然后断开套接口连接。在未连接UDP套接口上给两个数据报调用 函数sendto导致内枋执行下六步:
1、连接套接口
2、输出第一个数据报
3、断开套接口连接
4、连接套接口
5、输出第二个数据报
6、断开套接口连接
对于已连接UDP套接口,其步骤为:
1、连接套接口
2、输出第一个数据报
3、输出第二个数据报
服务器端:
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>#define SERV_PORT 9999
#define BUF_LEN 128void dg_echo(int sockfd, struct sockaddr_in *pcliaddr, socklen_t clilen)
{char buf[BUF_LEN]; socklen_t len;int n;for (;;) {len = clilen;if ((n = recvfrom(sockfd, buf, BUF_LEN, 0, (struct sockaddr*)pcliaddr, &len)) < 0) {printf("recvfrom error:%s\n", strerror(errno));continue;} sendto(sockfd, buf, n, 0, (struct sockaddr*)pcliaddr, len);}
}int main(int argc, char **argv)
{struct sockaddr_in servaddr, clientaddr;int sockfd;sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) {printf("socket error:%s\n", strerror(errno));return -1;}memset(&servaddr, 0x00, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);if (bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {printf("bind error:%s\n", strerror(errno));close(sockfd); return -1;}dg_echo(sockfd, &clientaddr, sizeof(clientaddr));return 0;
}
客户端:
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>#define SERV_PORT 9999
#define BUF_LEN 128char *sock_ntop(const struct sockaddr* sockaddr, socklen_t len)
{static char str[BUF_LEN];char portstr[7];struct sockaddr_in *sin;switch (sockaddr->sa_family) {case AF_INET:sin = (struct sockaddr_in*)sockaddr;if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == (const char *)NULL) {printf("inet_ntop error:%s\n", strerror(errno));return NULL;} if (ntohs(sin->sin_port) != 0) {snprintf(portstr, sizeof(portstr), ":%d", ntohs(sin->sin_port));strcat(str, portstr);}return str;} return NULL;
}void dg_cli(FILE *fp, int sockfd, const struct sockaddr_in * pservaddr, socklen_t servlen)
{int n;char sendline[BUF_LEN], recvline[BUF_LEN];struct sockaddr reply_addr;socklen_t len;if (connect(sockfd, (struct sockaddr*)pservaddr, servlen) < 0) {printf("connect error:%s\n", strerror(errno));return ;}while (fgets(sendline, BUF_LEN, fp) != NULL) {//sendto(sockfd, sendline, strlen(sendline), 0, (struct sockaddr*)pservaddr, servlen); write(sockfd, sendline, strlen(sendline);len = servlen;//n = recvfrom(sockfd, recvline, BUF_LEN, 0, &reply_addr, &len);n = read(sockfd, recvline, BUF_LEN);if (len != servlen || memcmp(&reply_addr, pservaddr, len) != 0) {printf("receive (%s) ignored\n", sock_ntop(&reply_addr, len));continue;}recvline[n] = 0;fputs(recvline, stdout);}
}int main(int argc, char **argv)
{struct sockaddr_in servaddr;int sock;memset(&servaddr, 0x00, sizeof(servaddr)); servaddr.sin_family = AF_INET;servaddr.sin_port = htons(SERV_PORT); if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) < 0) {printf("inet_pton error:%s\n", strerror(errno));return -1;}sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) {printf("socket error:%s\n", strerror(errno));return -1;}dg_cli(stdin, sock, &servaddr, sizeof(servaddr));return 0;
}
网络编程学习笔记(UDP的connect函数)相关推荐
- 网络编程学习笔记(getservbyname和getservbyport函数)
通过服务器的名字而不是服务器端口号来认知它,而且如果从主机到端口号的映射包含在一个文件中(一般是/etc/services),则如果端口号改变,我们所需做的所有改动就是改动文件/etc/service ...
- 网络编程学习笔记(readv和writev函数)
这两个函数与read和write相似,但readv和writev可以让我们在一个函数调用中读取多个缓冲区,这些操作被称为分散读和集中写.其函数原型为: #include <sys/uio.h&g ...
- 网络编程学习笔记(recv和send函数)
与read和write函数相似,只是多了一个附加的参数,其函数原型为: #include <sys/socket.h> ssize_t recv(int sockfd, void *buf ...
- 网络编程学习笔记(非阻塞connect)
设置非阻塞,如果返回EINPROGRESS,表示正在建立连接,还没有完成 非阻塞的三个用途: 1.我们可以在三路握手的同时做其它的处理.connect要花一个往返时间完成,而且可以是在任何地主,从几个 ...
- 网络编程学习笔记(recvmsg和sendmsg函数)
这两个函数是最通用的I/O函数.实际上,可以用recvmsg代替read.readv.recv和redvfrom.同样,各种输出函数都可以用sendmsg取代 #include<sys/sock ...
- 网络编程学习笔记(recvfrom和sendto函数)
其原型为: #include <sys/socket.h>ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags ...
- 网络编程学习笔记(getsockopt和setsockopt函数)
其原型为: #include <sys/socket.h> int getsockopt(int sockfd, int level, int optname, void *optval, ...
- [Linux网络编程学习笔记]索引
一.Linux基本知识 [学习笔记]Linux平台的文件I/O操作 [学习笔记]Linux平台的文件,目录及操作 [Linux学习笔记]标准输入输出 [Linux学习笔记]进程概念及控制 [Linux ...
- 15Java网络编程学习笔记
Java网络编程学习笔记 文章目录 1 网络基础 1.1 网络通信 1.2 网络 1.3 IP地址 1.5 域名 1.6 端口号 1.7 网络通信协议 1.8 TCP协议 1.9 UDP协议 2 In ...
最新文章
- Linux中获取当前程序路径的方法
- 40 JavaScript中的高阶函数
- 将h.264视频流封装成flv格式文件(一.flv格式)
- Linux基础书籍推荐
- 无人值守网络安装Linux系统
- 限界分支法(队列方式)追踪解:01背包问题
- 一天一个设计模式之建造者模式(Builder)
- linux测量某个ip的网速,linux下测网速
- nginx 电子书_13本免费的电子书,拿走,不谢
- 面向项目(十一)—— 库的使用
- java程序结构化设计_项目二:基于Java的结构化程序设计
- HDU 1394 求逆序数(线段树)
- matlab自适应遗传算法代码,自适应遗传算法MATLAB代码
- 南宁研祥智谷远程预付费电能管理系统的应用
- 计算机的工作原理(冯诺依曼体系)
- keil出现no source“: Error: command-line: #564: cannot open解决方法
- 手机APP开发之MIT Appinventor详细实战教程(十),标准登陆界面的逻辑设计和数据库的有效使用
- NLP文本分析(文本分类与句子评分)
- OD和CE使用示例-Python实现win98扫雷一键标雷外挂
- 去除标点符号乱码quot---转义字符
热门文章
- 像诗一样的 Javascript 代码(转)
- TCP服务器:多进程
- 购买Entrust SSL 数字证书?你怎么看?
- ldconfig及LD_LIBRARY_PATH
- windows7下载python教程-Windows 7下Python Web环境搭建图文教程
- vscode使用教程python-如何在VSCode上轻松舒适的配置Python的方法步骤
- python语法手册-python语法手册
- python好学吗mooc中文网-Python的N种玩法_中国大学MOOC(慕课)
- 初学者python编辑器-分享|Mu 入门:一个面向初学者的 Python 编辑器
- python入门代码示例-这可能是最好玩的python GUI入门实例!