对于已连接的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函数)相关推荐

  1. 网络编程学习笔记(getservbyname和getservbyport函数)

    通过服务器的名字而不是服务器端口号来认知它,而且如果从主机到端口号的映射包含在一个文件中(一般是/etc/services),则如果端口号改变,我们所需做的所有改动就是改动文件/etc/service ...

  2. 网络编程学习笔记(readv和writev函数)

    这两个函数与read和write相似,但readv和writev可以让我们在一个函数调用中读取多个缓冲区,这些操作被称为分散读和集中写.其函数原型为: #include <sys/uio.h&g ...

  3. 网络编程学习笔记(recv和send函数)

    与read和write函数相似,只是多了一个附加的参数,其函数原型为: #include <sys/socket.h> ssize_t recv(int sockfd, void *buf ...

  4. 网络编程学习笔记(非阻塞connect)

    设置非阻塞,如果返回EINPROGRESS,表示正在建立连接,还没有完成 非阻塞的三个用途: 1.我们可以在三路握手的同时做其它的处理.connect要花一个往返时间完成,而且可以是在任何地主,从几个 ...

  5. 网络编程学习笔记(recvmsg和sendmsg函数)

    这两个函数是最通用的I/O函数.实际上,可以用recvmsg代替read.readv.recv和redvfrom.同样,各种输出函数都可以用sendmsg取代 #include<sys/sock ...

  6. 网络编程学习笔记(recvfrom和sendto函数)

    其原型为: #include <sys/socket.h>ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags ...

  7. 网络编程学习笔记(getsockopt和setsockopt函数)

    其原型为: #include <sys/socket.h> int getsockopt(int sockfd, int level, int optname, void *optval, ...

  8. [Linux网络编程学习笔记]索引

    一.Linux基本知识 [学习笔记]Linux平台的文件I/O操作 [学习笔记]Linux平台的文件,目录及操作 [Linux学习笔记]标准输入输出 [Linux学习笔记]进程概念及控制 [Linux ...

  9. 15Java网络编程学习笔记

    Java网络编程学习笔记 文章目录 1 网络基础 1.1 网络通信 1.2 网络 1.3 IP地址 1.5 域名 1.6 端口号 1.7 网络通信协议 1.8 TCP协议 1.9 UDP协议 2 In ...

最新文章

  1. Linux中获取当前程序路径的方法
  2. 40 JavaScript中的高阶函数
  3. 将h.264视频流封装成flv格式文件(一.flv格式)
  4. Linux基础书籍推荐
  5. 无人值守网络安装Linux系统
  6. 限界分支法(队列方式)追踪解:01背包问题
  7. 一天一个设计模式之建造者模式(Builder)
  8. linux测量某个ip的网速,linux下测网速
  9. nginx 电子书_13本免费的电子书,拿走,不谢
  10. 面向项目(十一)—— 库的使用
  11. java程序结构化设计_项目二:基于Java的结构化程序设计
  12. HDU 1394 求逆序数(线段树)
  13. matlab自适应遗传算法代码,自适应遗传算法MATLAB代码
  14. 南宁研祥智谷远程预付费电能管理系统的应用
  15. 计算机的工作原理(冯诺依曼体系)
  16. keil出现no source“: Error: command-line: #564: cannot open解决方法
  17. 手机APP开发之MIT Appinventor详细实战教程(十),标准登陆界面的逻辑设计和数据库的有效使用
  18. NLP文本分析(文本分类与句子评分)
  19. OD和CE使用示例-Python实现win98扫雷一键标雷外挂
  20. 去除标点符号乱码quot---转义字符

热门文章

  1. 像诗一样的 Javascript 代码(转)
  2. TCP服务器:多进程
  3. 购买Entrust SSL 数字证书?你怎么看?
  4. ldconfig及LD_LIBRARY_PATH
  5. windows7下载python教程-Windows 7下Python Web环境搭建图文教程
  6. vscode使用教程python-如何在VSCode上轻松舒适的配置Python的方法步骤
  7. python语法手册-python语法手册
  8. python好学吗mooc中文网-Python的N种玩法_中国大学MOOC(慕课)
  9. 初学者python编辑器-分享|Mu 入门:一个面向初学者的 Python 编辑器
  10. python入门代码示例-这可能是最好玩的python GUI入门实例!