unix网络编程笔记

各种结构体:

struct sockaddr{
	unsigned short sa_family; /* 地址家族,AF_xxx */
	char sa_data[14]; /*14字节协议地址*/
};

struct sockaddr_in {
	short int sin_family; /* 通信类型 */
	unsigned short int sin_port; /* 端口 */                       2字节
	struct in_addr sin_addr; /* Internet 地址 */                  4字节
	unsigned char sin_zero[8]; /* 与sockaddr结构的长度相同*/     
		//8字节 (这三个参数一共14字节,使之与sockaddr相等互用)
};

struct in_addr {                        //一般socket函数中用char*来指向改结构体
  in_addr_t s_addr;
};
struct  hostent {
        char    * h_name;           /* official name of host */
        char    ** h_aliases;  /* alias list */
        short   h_addrtype;             /* host address type,  AF_INET  for TCP/IP*/
        short   h_length;               /* length of address,  32bit for IPv4*/
        char    ** h_addr_list; /* list of addresses */
#define h_addr  h_addr_list[0]          /* address, for backward compat */
        //h_addr 是指向的in_addr结构体的地址,通常*((struct in_addr *)h->h_addr) 来取IP地址
};


网络编程中的变量:

1、字符串类型的IP地址char *a:     “192.168.1.1”

2、字符串类型的主机名地址char *name:   “www.qq.com”

3、网络类型in_addr_t in:192.168.1.1


1、in_addr_t inet_addr(const char *cp);   //将字符串形的点分十进制转换成网络类型
用法:

in_addr in;
in = inet_addr("192.168.1.1");

2、char *inet_ntoa(struct in_addr in);  //将网络类型转换成字符串形的点分十进制

3、struct hostent* gethostbyname(const char *name);

用法:

struct hostent *ht;
ht = gethostbyname("www.QQ.com");


一、Berkeleysocket函数

第一部分是用于网络I/O的函数,如

accept、connect、closesocket/close、recv、recvfrom、select、send、sendto

第二部分是不涉及网络I/O、在本地端完成的函数,如

bind、getpeername、getsockname、getsocketopt、htonl、htons、inet_addr、inet_nton

ioctlsocket、listen、ntohl、ntohs、setsocketopt、shutdow、socket等

第三部分是检索有关域名、通信服务和协议等Internet信息的数据库函数,如

gethostbyaddr、gethostbyname、gethostname、getprotolbyname

getprotolbynumber、getserverbyname、getservbyport


关于阻塞和非阻塞,第二部分“不涉及网络I/O、本地端工作“的函数是非阻塞函数;网络I/O的函数是可阻塞函数,也就是它们可以阻塞执行,也可以不阻塞执行。这些函数都使用了一个socket,如果它们使用的socket是阻塞的,则这些函数是阻塞函数;如果它们使用的socket是非阻塞的,则这些函数是非阻塞函数。 默认创建的socket是阻塞的。


阻塞情况:

connect函数:找IP地址对应的主机途中会阻塞,如果找到IP地址对应的主机,并且对应端口在listen状态就会返回0(表示成功),否则返回-1(表示失败)。注意:失败后的sockfd必须关闭,不能再用connect来连接,需重新socket一个新sockfd。

accept函数:若已连接队列里取客户端套接口,如果已连接队列为空,则阻塞。

TCP中的read、write、send、recv等阻塞情况:

每个已经建立TCP连接的套接口拥有两个队列——“发送缓冲区”和“接收缓冲区”。

1、调用read和recv时,若缓冲区有数据就会返回,否则会阻塞直到有数据。

2、调用write和send时,当发送缓冲区空闲大小大于发送数据的大小则会直接返回(并非需要对端调用recv),否则阻塞直到空闲位置足够大小。



二、

1、bind函数

服务器可以同时bind指定的IP地址(因为一台服务器可能有多个网络借口或IP地址)和端口,意义是:监听指定IP和端口。

例如:在同一个机子里运行以下的服务器客户端

服务端bind指定IP:

addr.sin_addr.s_addr =inet_addr("192.168.1.103");  //内网IP号
addr.sin_port=htons(13);
bind(skfd,(sockaddr*)&addr,sizeof(sockaddr_in));

客户端通过回流地址访问服务器:

servaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
servaddr.sin_port   = htons(13);
connect(sockfd, (sockaddr *) &servaddr, sizeof(servaddr));

运行结果:connect失败返回。因为就算客户端通过回流方式链接本机的服务端,由于服务端bind了192.168.1.103,只能通过192.168.1.103来访问服务器。

但可以bind定特殊宏INADDR_ANY(通配地址)表明任何服务器监听任意一个IP地址。


2、accept函数

 int   accept(int   sockfd,   void   *addr,   int   *addrlen);   

accept参数里的sockfd是监听sockfd,返回的是新的已连接sockfd,已连接sockfd和监听sockfd同一个端口但不同等(此时close掉监听sockfd是不影响已连接sockfd的读写)。

同时,sockfd是一个文件描述符,内有计数器。当父进程accept产生新的已连接sockfd时,fork一个子进程,子进程会复制父进程的sockfd并计数器+1。此时若父进程close掉sockfd,也不会影响子进程的对sockfd的读写,因为sockfd的计数器不为0,close并没真正关掉sockfd。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值