linux 网络编程-基础篇 #Socket简介 是一个编程接口
是一种特殊的文件描述符(everything in Unix is a file) 并不仅限于TCPIP协议
面向连接(Transmission Control Protocol - TCPIP)
无连接(User Datagram Protocol-UDP 和 Inter-Network Packet Exchange-IPX) #Socket类型
流式套接字(SOCK_STREAM)
提供了一个面向连接,可靠的数据传输服务,数据无差错,无重复的发送且 按发送顺序接收。内设置流量控制,避免数据流淹没慢的接收方。数据被看作是 字节流,无长度限制
数据报套接字(SOCK_DGRAM)
提供无连接服务。数据包以独立数据包的形式被发送,不提供无差错保证, 数据可能丢失或重复,顺序发送,可能乱序接收 原始套接字(SOCK_RAW)
可以对较低层次协议如IP,ICMP直接访问 #IP地址
IP地址是Internet中主机的标识
Internet中的主机要与别的机器通信必须具有一个IP地址 IP地址为32位(IPV4)或者128位(IPV6)
每个数据包都必须携带目的IP地址和源IP地址,路由器依靠此信息为数据包 选择路由
表示形式:常用点分形式,如202.38.64.10,最后都会转换为一个32位的无符号 整数。
#IP地址的转换 inet_aton()
将strptr所指的字符串转换成32位的网络字节序二进制值 int inet_aton(const char *strptr, struct in_addr *addrptr); inet_addr()
功能同上,返回转换后的地址
in_addr_t inet_addr(const char *strptr); inet_ntoa()
将32位网络字节序二进制地址转换成点分十进制的字符串。 char *inet_ntoa(struct in_addr inaddr); #端口号
为了区分一台主机接收到的数据包应该转交给哪个进程来进行处理,使用端口号 来区分
TCP端口号与UDP端口号独立(协议不同可以使用同一个端口) 三无组:协议,IP,端口
端口号一般由IANA(Internet Assigned Numbers Authority)管理
众所周知端口:1~1023(1~255之间为众所周知端口,256~1023端口通常由 UNIX系统占用
已登记端口:1024~49151 动态或私有端口:49152~65535 #字节序
不同类型CPU的主机中,内存存储多字节整数序列有两种方法,称为主机字节序(HBO): 小端序(little-endian)-低字节存储在低地址
将低字节存储在起始地址,称为\字节序,Intel,AMD等 采用的是这种方式
大端序(big-endian)-高序字节存储在低地址
将高字节存储在起始地址,称为\字节序,由ARM,Motorola 等所采用
网络中传输的数据必须按网络字节序,即大端字节序
在大部分PC机上,当应用进程将整数送入socket前,需要转化成网络字节序;当 应用进程从socket取出整数后,要转化成小端字节序 #字节序转换函数
把给定系统所采用的字节序称为主机字节序,为了避免不同类别主机之间在数据 交换时由于对于字节序的不用而导致的差错,引入了网络字节序 主机字节序到网络字节序: u_long htonl(u_long hostlong); u_short htons(u_short short); 网络字节序到主机字节序
u_long ntohl(u_long hostlong); u_short ntohs(u_short short); #网络编程相关API
int Socket(int domain, int type, int protocol);
int bind(int Sockfd, struct sockaddr *my_addr, int addrlen); int listen(int sockfd, in backlog);
int accept(int sockfd, struct sockaddr *addr, Socklen_t *addrlen); int connect(int sockfd, const struct sockaddr *addr, Socklen_t addrlen); ssize_t send(int sockfd, const void *buf, size_t len, int flags); ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, Socklen_t addrlen); ssize_t recv(int sockfd, void *buf, size_t len, int flags); ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, Socklen_t *addrlen); int shutdown(int sockfd, int how); #command: netstat -anpt #地址结构的一般用法
1.定义一个struct sockaddr_in类型的变量并清空 struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr)); 2.填充地址信息
myaddr.sin_family = PF_INET; myaddr.sin_port = htons(8888);
myaddr.sin_addr.s_addr = inet_addr(\
3.将该变量强制转换为struct sockaddr类型在函数中使用 bind(listenfd,(struct sockaddr *)&myaddr, sizeof(myaddr)); #地址转换函数
unsigned long inet_addr(const char *address); int inet_aton(const char *cp, struct in_addr *inp); char *inet_ntoa(struct in_addr in); socket流程图:
附:代码 client.c
//int socket(int domain, int type, int protocol);
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); //int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); //uint16_t htons(uint16_t hostshort); //int atoi(const char *nptr);
//in_addr_t inet_addr(const char *cp); //void bzero(void *s, size_t n);
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); //int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
#include
#include
#include
#define N 64
int main(int argc, char *argv[]) {
if(argc < 3) {
printf(\,argv[0]); exit(-1); }
int sockfd;
struct sockaddr_in myaddr,peeraddr; char buf[N] = {0}; size_t n;
socklen_t mylen,peerlen; mylen = sizeof(myaddr);
peerlen = sizeof(peeraddr); /* creat socket */
if(-1 == (sockfd = socket(AF_INET,SOCK_DGRAM,0))) {
perror(\); exit(-1); }
/* bind initialization */
bzero(&myaddr,sizeof(myaddr)); myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(atoi(argv[2])+1); myaddr.sin_addr.s_addr = inet_addr(argv[1]); /* bind */
if(-1 == bind(sockfd, (struct sockaddr *)&myaddr, mylen)) {
perror(\); exit(-1); }
/* connect */
bzero(&peeraddr, sizeof(peeraddr)); peeraddr.sin_family = AF_INET;
peeraddr.sin_port = htons(atoi(argv[2]));
peeraddr.sin_addr.s_addr = inet_addr(argv[1]);
//connect(sockfd,(struct sockaddr *)&peeraddr, peerlen); while(1){
fgets(buf, N, stdin); printf(\,buf);
if(-1 == (n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&peeraddr, peerlen))) {
perror(\); exit(-1); }
if(strncmp(buf, \, 4) == 0) break;
printf(\,n); }
close(sockfd); exit(0); }
server.c
#include
#include