`
pypcjs
  • 浏览: 5603 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
最近访客 更多访客>>
社区版块
存档分类
最新评论

linux网络编程笔记

阅读更多
linux网络编程笔记
日期:2009-03-26
------------------------------
套接字类型:
1、 SOCK_STREAM (面向连接,TCP/IP)
2、 SOCK_DGRAM (无连接,UDP)

------------------------------
网络数据包结构体
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; /* 端口 */  
   struct in_addr sin_addr; /* Internet 地址 */  
   unsigned char sin_zero[8]; /* 与sockaddr结构的长度相同*/  
};  
struct in_addr {  
   unsigned long s_addr;  
};  
struct hostent {
    char    *h_name;        /* official name of host * /
    char    **h_aliases;    /* alias list */
    int     h_addrtype;     /* host address type */
    int     h_length;       /* length of address */
    char    **h_addr_list;  /* list of addresses */
}

------------------------------
一些简单的缩写表示
h => host
2 => to
n => network
s => short(从本机字节顺序转 换为网络字节顺序。)

htons() => h-to-n-s => Host to Network Short
htonl() => h-to-n-l => Host to Network Long
ntohs() => n-to-h-s => Network to Host Short
ntohl() => n-to-h-l => Network to Host Long

------------------------------
网络IP地址及处理
一、将IP地址从点数格式转换成无符号长整型。
	struct sockaddr_in ina;
	ina.sin_addr.s_addr = inet_addr("132.241.5.10"); /*inet_addr发生错误时,返回-1*/
	
二、 in_addr 结构体输出成点数格式
	inet_ntoa()("ntoa"的含义是"network to ascii"), 
	printf("%s",inet_ntoa(ina.sin_addr)); 
使用inet_ntoa需要注意的是:
	1、inet_ntoa()将结构体in-addr作为一 个参数,不是长整形。
	2、它返回的是一个指向一个字符串的指针。它是一个由inet_ntoa()控制的静态的固定的指针,所以每次调用inet_ntoa(),它就将覆盖上次调用时所得的IP地址。

char *a1, *a2; 
a1 = inet_ntoa(ina1.sin_addr); /* 这是198.92.129.1 */ 
a2 = inet_ntoa(ina2.sin_addr); /* 这是132.241.5.10 */ 
printf("address 1: %s\n",a1); 
printf("address 2: %s\n",a2); 
输出如下: 
address 1: 132.241.5.10 
address 2: 132.241.5.10 

------------------------------
socket()函数  
#include <sys/types.h>
#include <sys/socket.h>  
/**
*返回socket描述符。
*return:错误发生时返回-1.
*/
int socket(int domain, int type, int protocol);  

domain: 应该设置成 "AF_INET",就象上面的数据结构struct sockaddr_in 中一样。
type: SOCK_STREAM 或者 SOCK_DGRAM
protocol: 一般为0

------------------------------
bind()函数 
#include <sys/types.h>
#include <sys/socket.h>
/**
*客户端绑定的端口号,端口号为0时表示随机选择一个可用的端口号。
*return: 发生错误时返回-1
*/
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);  

sockfd:  是调用 socket 返回的文件描述符。
my_addr: 是指向数据结构 struct sockaddr 的指针,它保存你的地址(即端口和 IP 地址) 信息。 
addrlen: 设置为 sizeof(struct sockaddr)。  

my_addr.sin_port = htons(0); /* 随机选择一个没有使用的端口 */  
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);/* 使用自己的IP地址 */  

------------------------------
connect()函数 
#include <sys/types.h>
#include <sys/socket.h>
/**
*
*return: 发生错误时返回-1
*/ 
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);  

sockfd:     是系统调用 socket() 返回的套接字文件描述符。
serv_addr:  是 保存着目的地端口和 IP 地址的数据结构 struct sockaddr。
addrlen:    设置 为 sizeof(struct sockaddr)。  

------------------------------
listen()函数 
/**
*return: 发生错误时返回-1
*/
int listen(int sockfd, int backlog);

sockfd:  是调用 socket() 返回的套接字文件描述符。
backlog: 是在进入队列中允许的连接数目。进入的连接是在队列中一直等待,直到你接受( accept() ) 连接。它们的数目限制于队列的允许。大多数系统的允许数目是20,你也可以设置为5到10。 

------------------------------
accept()函数 
#include <sys/socket.h>
int accept(int sockfd, void *addr, int *addrlen); 

sockfd  是调用 socket() 返回的套接字文件描述符。
addr    是个指向局部的数据结构 sockaddr_in 的指针。这是要求接入的信息所要去的地 方(你可以测定那个地址在那个端口呼叫你)。在它的地址传递给 accept 之 前。
addrlen 是个局部的整形变量,设置为 sizeof(struct sockaddr_in)。 

------------------------------
send() and recv()函数 
这两个函数用于流式套接字或者数据报套接字的通讯。
int send(int sockfd, const void *msg, int len, int flags); 
 
sockfd: 是你想发送数据的套接字描述符(或者是调用 socket() 或者是 accept() 返回的。)
msg:    是指向你想发送的数据的指针。
len:    是数据的长度。 把 flags 设置为 0 就可以了。

send() 返回实际发送的数据的字节数--它可能小于你要求发送的数目.
注意,有时候你告诉它要发送一堆数据可是它不能处理成功。它只是 发送它可能发送的数据,然后希望你能够发送其它的数据。
记住,如果 send() 返回的数据和 len 不匹配,你就应该发送其它的数据。但是这里也 有个好消息:如果你要发送的包很小(小于大约 1K),它可能处理让数据一 次发送完。最后要说得就是,它在错误的时候返回-1,并设置 errno。 

recv() 函数
int recv(int sockfd, void *buf, int len, unsigned int flags); 
sockfd 是要读的套接字描述符。
buf 是要读的信息的缓冲。
len 是缓 冲的最大长度。
flags 可以设置为0。(请参考recv() 的 man page。) recv() 返回实际读入缓冲的数据的字节数。或者在错误的时候返回-1, 同时设置 errno。 

------------------------------
sendto() 和 recvfrom()函数 
int sendto(int sockfd, const void *msg, int len, unsigned int flags,  
		const struct sockaddr *to, int tolen);  
		
struct sockaddr 的指针,它包含了目的地的 IP 地址和端口信息。
tolen 可以简单地设置为 sizeof(struct sockaddr)。 

int recvfrom(int sockfd, void *buf, int len, unsigned int flags,  
		struct sockaddr *from, int *fromlen); 

from 是一个指向局部数据结构 struct sockaddr 的指针,它的内容是源机器的 IP 地址和端口信息。
fromlen 是个 int 型的局部指针,它的初始值为 sizeof(struct sockaddr)。
		
记住,如果你用 connect() 连接一个数据报套接字,你可以简单的调 用 send() 和 recv() 来满足你的要求。这个时候依然是数据报套接字,依 然使用 UDP,系统套接字接口会为你自动加上了目标和源的信息。 

------------------------------
close()和shutdown()函数 
int close(int sockfd);

int shutdown(int sockfd, int how);  
sockfd 是你想要关闭的套接字文件描述复。
how 的值是下面的其中之 一: 
  0 – 不允许接受 
  1 – 不允许发送 
  2 – 不允许发送和接受(和 close() 一样) 
shutdown() 成功时返回 0,失败时返回 -1

------------------------------
getpeername()函数 
#include <sys/socket.h>
int getpeername(int sockfd, struct sockaddr *addr, int *addrlen); 
sockaddr_in 的指针,它保存着连接的另一边的 信息。
addrlen 是一个 int 型的指针,它初始化为 sizeof(struct sockaddr)。 
函数在错误的时候返回 -1
一旦你获得它们的地址,你可以使用 inet_ntoa() 或者 gethostbyaddr() 来打印或者获得更多的信息。

------------------------------
gethostname()函数
#include <unistd.h>
int gethostname(char *hostname, size_t size); 
获取程序所运行的机器的主机名字

hostname 是一个字符数组指针,它将在函数返回时保存 主机名。
size是hostname 数组的字节长度。 

------------------------------
gethostbyname()函数
#include <netdb.h>
struct hostent *gethostbyname(const char *name);
返回一个指向 struct hostent 的指针。
struct hostent {
    char    *h_name;        /* official name of host * /
    char    **h_aliases;    /* alias list */
    int     h_addrtype;     /* host address type */
    int     h_length;       /* length of address */
    char    **h_addr_list;  /* list of addresses */
}
h_name – 地址的正式名称。 
h_aliases – 空字节-地址的预备名称的指针。 
h_addrtype –地址类型; 通常是AF_INET。  
h_length – 地址的比特长度。 
h_addr_list – 零字节-主机网络地址指针。网络字节顺序。 
h_addr - h_addr_list中的第一地址。 




 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics