使用套接字计算机通信编程心得,网络编程学习心得1

总结

TCP流套接字

0.一些细节

0.1数据结构

通用套接字接口

struct sockaddr

{

Uint8_t sa_lenunsigned short sa_family; /*地址家族, AF_xxx */char sa_data[14]; /*14字节协议地址*/

}

sa_family能够是各种各样的类型,

sa_data包含套接字中的目标地址和端口信息。

这好像有点不明智。为了处理struct sockaddr,程序员创造了一个并列的结构:struct sockaddr_in ("in"代表"Internet"。)

struct sockaddr_in

{

Uint8_t sin_lenshort int sin_family; /*通信类型*/unsigned short int sin_port; /*端口*/struct in_addr sin_addr; /* Internet地址*/unsigned char sin_zero[8]; /*与sockaddr结构的长度相同*/

}

我们一般只需要定义sin_family,

sin_port和sin_addr选项。

套接口地址结构有sockaddr_in,sockaddr_in6,sockaddr_un(unix套接字)等等

从程序员的角度来看,通用套接口地址的唯一用途是指向特定与协议的地址结构的指针转换类型,(就是给人转换用的,比如,bind,connect函数中的等等,你用的啥协议,你就用啥套接口)

0.2参数传递

套接口地址结构传递给套接口函数时,总是通过指向结构的指针传递,然后在跟一个结构的长度,长度参数是否去地址,取决与传递方向,从进程传内核还是从内核传进程。

1从进程传内核,bind,connect,,sendto

Struct

sockaddr_in serv;

Connect(fd,(sa*)&serv,sizeof(serv));

2.从内核传进程accept,getsockname

长度要取地址

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

0.3字节排序

大端小端big_endian,little_endian(低字节在地位)如何判断见程序unpv65

一些转换函数hton,ntoh(主要是转换sin_port)的

0.4 IP地址处理

旧的那些土函数就都别用了,直接用最好的inet_pton,和inet_ntop吧

0.5常用函数

socket()函数我想我不能再不提这个了-下面我将讨论一下socket()系统调用。下面是详细介绍:#include ;

#include ;

int socket(int domain, int type, int protocol);但 是它们的参数是什么?首先,domain应该设置成"AF_INET",就象上面的数据结构struct sockaddr_in中 一样。然后,参数type告诉内核是SOCK_STREAM类型还是SOCK_DGRAM类型。最后,把protocol设置为"0"。(注意:有很多种domain、type,我不可能一一列出了,请看socket()的man帮助。当然,还有一个"更好"的方式去得 到protocol。同时请查阅getprotobyname()的man帮助。)

socket()只是返回你以后在系统调用种可能用到的socket描述符,或者在错误的时候返回-1。全局变量errno中将储存返回的错误值。(请参考perror()的man帮助。)

bind()函数一旦你有一个套接字,你可能要将套接字和机器上的一定的端口关联起来。(如果你想用listen()来侦听一定端口的数据)

在bind()主题中最后要说的话是,在处理自己的IP地址和/或端口的时候,有些工作是可以自动处理的。my_addr.sin_port = 0; /*随机选择一个没有使用的端口*/my_addr.sin_addr.s_addr = INADDR_ANY; /*使用自己的IP地址*/通过将0赋给my_addr.sin_port,你告诉bind()自己选择合适的端口。同样,将my_addr.sin_addr.s_addr设置为INADDR_ANY,你告诉它自动填上它所运行的机器的IP地址。

为了防止出现“address already in use”在调用bind前记得调用setsockopt(listenfd,SOL,SOCKET,SO_REUSEADDR,&on,sizeof(on)

Connect()函数

调用connect将激发tcp的3次握手过程。

由于tc内置的connect超时相当长(一般为75秒),所以可以使用SIGALRM为connect设置超时。

具体方法是为这个信号,signal一个函数,在设置一个自己定义的超时时间

Listen()函数

第2个参数backlog即侦听队列的长度,它的真正含义是:侦听socket能处理的最大并发连接请求数,其最大取值为128。

半连接队列和已连接队列

Accept()函数

用tcp服务器调用,用于从已完成连接队列对头返回下一个已完成连接,如果已完成连接队列为空,那么进程被投入睡眠

Accept()函数得处理EINTR和ECONNABORTED(软件引起的连接夭折)的错误,而不能在碰到这些错误时候推出

断开连接close和shutdown()

你已经整天都在发送(send())和接收(recv())数据了,现在你准备关闭你的套接字描述符了。这很简单,你可以使用一般的Unix文件描述符的close()函数:close(sockfd);它将防止套接字上更多的数据的读写。任何在另一端读写套接字的企图都将返回错误信息。close是把描述字的引用技术减1,仅在该技术为0时才关闭他.

所以父进程必须关闭accept以后的套接字

如果你想在如何关闭套接字上有多一点的控制,你可以使用函数shutdown()。它允许你将一定方向上的通讯或者双向的通讯(就象close()一样)关闭,你可以使用:int shutdown(int sockfd, int how);

sockfd是你想要关闭的套接字文件描述复。how的值是下面的其中之一:SHUT_RD

SHUT_WR

SHUT_RDWR

shutdown()成 功时返回0,失败时返回-1(同时设置errno。)如果在无连接的数据报套接字中使用shutdown(), 那么只不过是让send()和recv()不能使用(记住你在数据报套接字中使用了connect后是可以使用它们的)。

Getsockname()和getpeername()

2个函数参数一样

Getsockname()返回用内核赋予该连接的本地ip地址和本地端口号

函数getpeername()告诉你在连接的流式套接字上谁在另外一边。

gethostname()函数甚至比getpeername()还简单的函数是gethostname()。它返回你程序所运行的机器的主机名字。然后你可以使用gethostbyname()以获得你的机器的IP地址。下面是定义:#include ;

int gethostname(char *hostname, size_t size);参数很简单:hostname是一个字符数组指针,它将在函数返回时保存主机名。size是hostname数组的字节长度。函数调用成功时返回0,失败时返回-1,并设置errno。

struct hostent *gethostbyname(const char *name);很明白的是,它返回一个指向struct hostent的指针。这个数据结构是这样的:struct hostent {char *h_name;char **h_aliases;int h_addrtype;int h_length;char **h_addr_list;};#define h_addr h_addr_list[0]这里是这个数据结构的详细资料:struct hostent:h_name –地址的正式名称。h_aliases –空字节-地址的预备名称的指针。h_addrtype –地址类型;通常是AF_INET。h_length –地址的比特长度。h_addr_list –零字节-主机网络地址指针。网络字节顺序。h_addr - h_addr_list中的第一地址。gethostbyname()成功时返回一个指向结构体hostent的指针,或者是个空(NULL)指针。(但是和以前不同,不设置errno,h_errno设置错误信息。请看下面的herror()。)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值