抽象理解:http://www.cnblogs.com/dolphinX/p/3460545.html
SOCKET (domain协议域AF_INET,type类型SOCK_STREAM,protocol协议IPPROTO_TCP)
说明:套接字,编程接口API,返回【描述符】,失败则-1;描述符在进程空间的【描述符表】,数据结构在内核缓冲里。根据指定的地址族、数据类型和协议来分配一个socket的描述字及其所用的资源。原理:C发送连接请求→等待连接中的S→接受确认并请求数据;C→wrc;S→rwrc 。
SOCKET 编程API:
1、绑定:int bind(SOCKET socket描述符,const struct sockaddr *address地址及端口,socketlen_t address_len长度);
把一个地址族中的特定地址赋给socket。S——启动——bing()——地址——提供服务。C——系统随机生成。
成功:返回0 ;失败:SOCKET_ERROR;
2、监听:int listen(int sockfd, int backlog排队的最大连接个数);
3、connect(int sockfd, const struct sockaddr *addr服务器socket地址, socklen_t addrlen);
4、接收:int recv(SOCKET socket描述字, char FAR* buf, int len缓冲区长度, int flags调用方式);
正常:返回读入字节数;接收中止:返回0;失败:SOCKET_ERROR;
5、发送:int sendto( SOCKET s套接字, const char FAR* buf, int size, int flags, const struct sockaddr FAR* to, int tolen);
成功:返回读入字节数;失败:SOCKET_ERROR;
6、接受连接请求:int accept( int sockfd套接字描述符, struct socketaddr* addr返回连接地址, socklen_t* len);
成功:返回客户端的文件描述符,失败返回-1。
应用层:HTTP、FTP、DNS、SMTP、RPC、SNM
抽象层: Socket
传输层:TCL、UDP
网络层:IP、ICMP、IGMP
链路层:硬件接口、ARP、RARP
通信模式:
服务端——创建Socket——bing()绑定IP及端口——listen()监听——阻塞——accept()——recv()——close();
客户端——创建Socket——connect()连接指定端口——send()——close();
C/S循环机制:C_connect().j——S_accept().k——C_send().k+1——S_recv();
一握手:C向S发syn包(syn=j),C进入SYN_SEND;
二握手:S收syn包并确认k(ack=j+1),S向C发syn包(k),即SYN+ACK,服务器进入recv();
三握手:C收SYN+ACK包,且C向S发确认包ACK(ack=k+1)。
理解模型[Z字型]:A1发钱包——B1收到签字盖章——A2收到钱包及印章——B2
单词: host 主机 、router 路由器 、fiber 光线、Ethernet 以太网、satellite卫星
C语言实例:
服务端:
#include<winsock2.h>
#include<stdio.h>
#pragma comment(lib,"ws2_32.lib")
void main()
{
WSADATA wsaData;
SOCKET sockServer;
SOCKADDR_IN addrServer; //服务器地址
SOCKET sockClient;
SOCKADDR_IN addrClient; //客户端地址
WSAStartup(MAKEWORD(2,2),&wsaData); //启动命令
//bind绑定
sockServer=socket(AF_INET,SOCK_STREAM,0);
addrServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//INADDR_ANY表示任何IP
addrServer.sin_family=AF_INET; //2字节地址家族
addrServer.sin_port=htons(6000);//绑定端口6000
bind(sockServer,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));
//Listen监听端
listen(sockServer,5);//5为等待连接数目
printf("服务器已启动:\n监听中...\n");
int len=sizeof(SOCKADDR); //这个长度有什么用?
charsendBuf[100];//发送至客户端的字符串
charrecvBuf[100];//接受客户端返回的字符串
//会阻塞进程,直到有客户端连接上来为止
sockClient=accept(sockServer,(SOCKADDR*)&addrClient,&len); //接受连接请求
//接收并打印客户端数据
recv(sockClient,recvBuf,100,0);
printf("%s\n",recvBuf);
//关闭socket
closesocket(sockClient);
WSACleanup();} // 终止Winsock 2 DLL
客户端 (Client):
#include<winsock2.h>
#include<stdio.h>
#pragma comment(lib,"ws2_32.lib") //静态库文件
void main()
{
WSADATA wsaData; //存储WSAStartup函数返回的Windows Sockets数据
SOCKET sockClient;//客户端Socket
SOCKADDR_IN addrServer;//服务端地址(包含)
WSAStartup(MAKEWORD(2,2),&wsaData); //Windows网络编程接口启动命令,在winsock2.h头文件
//新建客户端socket
sockClient=socket(AF_INET,SOCK_STREAM,0);
//定义要连接的服务端地址
addrServer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//目标IP(127.0.0.1是回送地址)
addrServer.sin_family=AF_INET;
addrServer.sin_port=htons(6000);//连接端口6000
//连接到服务端
connect(sockClient,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));
//发送数据
char message[20]="HelloSocket!";
send(sockClient,message,strlen(message)+1,0);
//关闭socket
closesocket(sockClient);
WSACleanup();}
/*SOCKADDR结构*/
struct sockaddr
{
unsigned short sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
/*SOCKADDR_IN*/
struct sockaddr_in
{
short int sin_family; /* Address family 协议族*/
unsigned short int sin_port; /* Port number 端口号*/
struct in_addr sin_addr; /* Internet address IP地址*/
unsigned char sin_zero[8]; /* Same size as struct sockaddr 为使二者大小相同而保留的空字节*/
};
其中in_addr结构的定义如下:
typedef struct in_addr {
union {
struct{ unsigned char s_b1,s_b2, s_b3,s_b4;} S_un_b; //四个字节
struct{ unsigned short s_w1, s_w2;} S_un_w; //两个双字节
unsigned long S_addr; //长整型
} S_un;
} IN_ADDR;
共用体:三种表示方法,
inet_addr函数最简单——addrto.sin_addr.s_addr=inet_addr("192.168.0.2");