#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)-低字节存储在低地址将低字节存储在起始地址,称为"Little-Endian"字节序,Intel,AMD等采用的是这种方式大端序(big-endian)-高序字节存储在低地址将高字节存储在起始地址,称为"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);
#网络编程相关APIint 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("192.168.1.100");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 <stdio.h>#include <sys/types.h>//socket():bind();listen():accept();listen();accept();connect();#include <sys/socket.h>//socket():bind();listen():accept();inet_addr();listen():accept();connect();#include <arpa/inet.h>//htons();inet_addr():#include <netinet/in.h>//inet_addr():#include <strings.h>//bzero();#include <stdlib.h>//atoi();exit();#include <unistd.h>//close():#include <string.h>#define N 64int main(int argc, char *argv[]){ if(argc < 3) { printf("Using: %s ip port/n",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("socket"); 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("bind"); 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:%s",buf); if(-1 == (n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&peeraddr, peerlen))) { perror("sendto"); exit(-1); } if(strncmp(buf, "quit", 4) == 0) break; printf("n = %d/n",n); } close(sockfd); exit(0);}复制代码server.c复制代码#include <stdio.h>#include <sys/types.h>//socket():bind();listen():accept();listen();accept();connect();#include <sys/socket.h>//socket():bind();listen():accept();inet_addr();listen():accept();connect();#include <arpa/inet.h>//htons();inet_addr():#include <netinet/in.h>//inet_addr():#include <strings.h>//bzero();#include <stdlib.h>//atoi();exit();#include <unistd.h>//close():#include <string.h>#define N 64typedef struct sockaddr SA;int main(int argc, char *argv[]){ if(argc < 3) { printf("Using: %s ip port/n",argv[0]); exit(-1); } int listenfd, connfd; struct sockaddr_in myaddr, peeraddr; char buf[N] = {0}; size_t n; socklen_t mylen, peerlen; mylen = sizeof(myaddr); peerlen = sizeof(peeraddr); /* create socket */ if ((listenfd = (socket(PF_INET, SOCK_DGRAM, 0))) < 0) { perror("socket"); exit(-1); } /* bind initialization */ bzero(&myaddr, mylen); myaddr.sin_family = PF_INET; myaddr.sin_port = htons(atoi(argv[2])); inet_aton(argv[1], &myaddr.sin_addr); if(bind(listenfd,(SA *)&myaddr, sizeof(myaddr)) < 0) { perror("bind"); exit(-1); } /* listen */ listen(listenfd, 5); /* accept */ if(-1 == (connfd = accept(listenfd, (SA *)&peeraddr, &peerlen))) { perror("accept"); exit(-1); } printf("connect from %s: %d/n",inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port)); /* recv-send */ while(1){ n = recv(connfd, buf, N, 0); buf[n] = 0; printf("n = %d---%s/n",n,buf); if(0 == strncmp(buf,"quit",4)) break; send(connfd, buf, strlen(buf), 0); } close(connfd); close(listenfd); exit(0);}原文链接:http://www.VEVb.com/lr-ting/archive/2012/08/24/2652482.html
新闻热点
疑难解答