第四章 基本tcp 套接口编程

注意区分AF_XXX 和PF_XXX,AF代表address family, PF代表protocol family。

1 socket 函数

2 connect 函数

3 bind 函数

4 listen 函数

注:主动、被动 与 服务器、客户端没有明确的对应关系
linux中定义backlog为 完成队列的最大个数
5 accept 函数
5 getsockname和getpeername的用法及实例
getsockname和getpeername

#include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);
int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);
返回:0—OK,-1—出错。

getsockname函数返回与套接口关联的本地协议地址。

getpeername函数返回与套接口关联的远程协议地址。

addrlen是值-结果参数。

使用场合:

  • 在不调用bind的TCP客户,当connect成功返回后,getsockname返回分配给此连接的本地IP地址和本地端口号;
  • 在以端口号为0调用bind后,使用getsockname返回内核分配的本地端口号;
  • getsockname可用来获取某套接口的地址族;
  • 在捆绑了通配IP地址的TCP服务器上,当连接建立后,可以使用getsockname获得分配给此连接的本地IP地址;
  • 当一个服务器调用exec启动后,他获得客户身份的唯一途径是调用getpeername函数。
  • 服务器code:
 #include    "unp.h"

 int
main(int argc, char ** argv)
{
int listenfd,connfd;
struct sockaddr_in servaddr;
pid_t pid;
char temp[]; listenfd = Socket(AF_INET, SOCK_STREAM, );
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons();
Bind(listenfd, (SA *)&servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
for( ; ; )
{
struct sockaddr_in local;
connfd = Accept(listenfd, (SA *)NULL, NULL);
if((pid = fork()) == )
{
Close(listenfd);struct sockaddr_in serv, guest;
char serv_ip[];
char guest_ip[];
socklen_t serv_len = sizeof(serv);
socklen_t guest_len = sizeof(guest);
getsockname(connfd, (struct sockaddr *)&serv, &serv_len);
getpeername(connfd, (struct sockaddr *)&guest, &guest_len);
Inet_ntop(AF_INET, &serv.sin_addr, serv_ip, sizeof(serv_ip));
Inet_ntop(AF_INET, &guest.sin_addr, guest_ip, sizeof(guest_ip));
printf("host %s:%d guest %s:%d\n", serv_ip, ntohs(serv.sin_port), guest_ip, ntohs(guest.sin_port));
char buf[] = "hello world";
Write(connfd, buf, strlen(buf));
Close(connfd);
exit();
}
Close(connfd);
}
}

client code

 #include "unp.h"
#define DEST_IP "127.0.0.1" int
main(int argc, char ** argv)
{
int sockfd, n;
char buf[];
char serv_ip[], guest_ip[];
struct sockaddr_in servaddr; sockfd = Socket(AF_INET, SOCK_STREAM, );
bzero(&servaddr, sizeof(struct sockaddr_in));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(); Inet_pton(AF_INET, DEST_IP, &servaddr.sin_addr);
Connect(sockfd, (SA *)&servaddr, sizeof(servaddr)); struct sockaddr_in serv, guest;
socklen_t serv_len = sizeof(serv);
socklen_t guest_len = sizeof(guest); getsockname(sockfd, (SA *)&guest, &guest_len);
getpeername(sockfd, (SA *)&serv, &serv_len); Inet_ntop(AF_INET, &guest.sin_addr, guest_ip, sizeof(guest_ip));
Inet_ntop(AF_INET, &serv.sin_addr, serv_ip, sizeof(serv_ip)); printf("host %s:%d, guest %s:%d\n", serv_ip, ntohs(serv.sin_port), guest_ip, ntohs(guest.sin_port)); n = Read(sockfd, buf, );
buf[n] = '\0';
printf("%s\n", buf);
Close(sockfd);
exit();
}

TCP

对于服务器来说,在bind以后就可以调用getsockname来获取本地地址和端口,虽然这没有什么太多的意义。getpeername只有在链接建立以后才调用,否则不能正确获得对方地址和端口,所以他的参数描述字一般是链接描述字而非监听套接口描述字。

对于客户端来说,在调用socket时候内核还不会分配IP和端口,此时调用getsockname不会获得正确的端口和地址(当然链接没建立更不可能调用getpeername),当然如果调用了bind 以后可以使用getsockname。想要正确的到对方地址(一般客户端不需要这个功能),则必须在链接建立以后,同样链接建立以后,此时客户端地址和端口就已经被指定,此时是调用getsockname的时机。

CP状态图:
 
 

Unix 网络编程 读书笔记3的更多相关文章

  1. UNIX网络编程--读书笔记

    会集中这段时间写UNIX网络编程这本书的读书笔记,准备读三本,这一系类的文章会不断更新,一直会持续一个月多,每篇的前半部分是书中讲述的内容,每篇文章的后半部分是自己的心得体会,文章中的红色内容是很重要 ...

  2. UNIX网络编程读书笔记:简介

    认知套接口编程接口 理解原始套接口(raw socket)的概念   值得注意的是,客户和服务器是典型的用户进程,而TCP和IP协议则通常是系统内核协议栈的一部分. 上图中在TCP和UDP之间留有间隙 ...

  3. Unix 网络编程 读书笔记1

    第一章: C/C++语言提供两种不同的编程模式:IPL32和PL64.► IPL32 ● 表示integer/pointer/long三种数据类型是32位(4个字节),在这种模式下,提供32位的地址空 ...

  4. UNIX网络编程读书笔记:原始套接口

    概述 应用程序可以绕过传输层而直接使用IPv4和IPv6,这称为原始套接口(raw socket).http://www.cnblogs.com/nufangrensheng/p/3583435.ht ...

  5. UNIX网络编程读书笔记:套接口选项

    概述 有很多方法来获取和设置影响套接口的选项: getsockopt和setsockopt函数 fcntl函数 ioctl函数 getsockopt和setsockopt函数 这两个函数仅用于套接口. ...

  6. UNIX网络编程读书笔记:I/O模型(阻塞、非阻塞、I/O复用、信号驱动、异步)

    I/O模型 UNIX下可用的5种I/O模型: (1)阻塞I/O (2)非阻塞I/O (3)I/O复用(select和poll) (4)信号驱动I/O(SIGIO) (5)异步I/O 对于一个套接口上的 ...

  7. Unix 网络编程 读书笔记2

    第三章 套接字编程简介 每一个 Socket 都用一个半相关描述:{协议,本地地址,本地端口}一个完整的 Socket 则用一个相关描述{协议,本地地址,本地端口,远程地址,远程端口}每一个 Sock ...

  8. UNIX网络编程读书笔记:UNIX域协议

    概述 UNIX域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务器通信的一种方法,所用API与在不同主机上执行客户/服务器通信所用的API(套接口API)相同.UNIX域协议可视为进程间通信 ...

  9. UNIX网络编程读书笔记:基本TCP套接口编程

    编写一个完整的TCP客户和服务器程序所需要的基本套接口函数: 1.socket函数(客户端.服务器端都必须调用) 参数family指明协议族(family),该参数也往往被称为协议域(domain). ...

  10. UNIX网络编程读书笔记:辅助数据

    辅助数据(ancillary data)可通过调用sendmsg和recvmsg这两个函数,使用msghdr结构中的msg_control和msg_controllen这两个成员发送和接收. 辅助数据 ...

随机推荐

  1. JAVA设计模式之门面模式(外观模式)

    医院的例子 现代的软件系统都是比较复杂的,设计师处理复杂系统的一个常见方法便是将其“分而治之”,把一个系统划分为几个较小的子系统.如果把医院作为一个子系统,按照部门职能,这个系统可以划分为挂号.门诊. ...

  2. Assembly类

    System.Reflection.Assembly类是一个比较常用到的类,在反射中就经常用到. 由于这个类实在有太多的字段.属性与方法.实在不想将一个个属性方法从MSDN复制出来然后逐个属性.方法敲 ...

  3. 线程系列07,使用lock语句块或Interlocked类型方法保证自增变量的数据同步

    假设多个线程共享一个静态变量,如果让每个线程都执行相同的方法每次让静态变量自增1,这样的做法线程安全吗?能保证自增变量数据同步吗?本篇体验使用lock语句块和Interlocked类型方法保证自增变量 ...

  4. 用最简单的例子理解备忘录模式(Memento Pattern)

    简单来说,备忘录模式就是支持回退操作.假设让一个Notepad支持回退操作,如何实现呢? 首先需要一个备忘录类. public class Memento { private string _msg; ...

  5. dubbo白名单通过filter,spring web通过拦截器或者filter即可

    在开发中,有时候需要限制访问的权限,白名单就是一种方法.对于Java Web应用,Spring的拦截器可以拦截Web接口的调用:而对于dubbo接口,Spring的拦截器就不管用了. dubbo提供了 ...

  6. 【linux】centos7终端中文显示乱码,命令返回中文乱码

    centos7终端中文显示乱码,命令返回中文乱码 1.查看服务器编码的命令 1.1 echo $LANG 1.2 locale 1.3 查看终端xshell编码 如果以上的三点依旧保持一致,而依旧乱码 ...

  7. 算法:基于 RingBuffer 的 Queue 实现《续》

    背景 上篇实现了一个简单的队列,内部使用了 _count 计数,本文采用另外一种模式,不用 _count 计数. RingBuffer 不用 _count 计数的话,为了区分队列的满和空,需要在数组中 ...

  8. JDBC 通过PreparedStatement 对数据库进行增删改查

    1 插入数据 public boolean ChaRu3(User user){ boolean flag=true; Connection conn=null; PreparedStatement ...

  9. 反射 Reflect Modifier 修饰符工具类

    在查看反射相关的Class.Field .Constructor 等类时,看到他们都有这样一个方法:getModifiers():返回此类或接口以整数编码的 Java 语言修饰符.如需要知道返回的值所 ...

  10. WebChromeClient 简介 API 案例

    代码位置:https://github.com/baiqiantao/WebViewTest.git 设计思想理解 在WebView的设计中,不是什么事都要WebView类干的,有相当多的杂事是分给其 ...