没有收款接口网站怎么做收款,做赚钱问卷调查的网站好,网站公司维护,免费网站开发文章目录#xff1a;
一#xff1a;定义和流程分析
1.定义
2.流程分析
3.网络字节序
二#xff1a;相关函数
IP地址转换函数inet_pton inet_ntop#xff08;本地字节序 网络字节序#xff09;
socket函数(创建一个套接字)
bind函数(给socket绑定一个服务器地址结…文章目录
一定义和流程分析
1.定义
2.流程分析
3.网络字节序
二相关函数
IP地址转换函数inet_pton inet_ntop本地字节序 网络字节序
socket函数(创建一个套接字)
bind函数(给socket绑定一个服务器地址结构(IPport))
listen函数(设置最大连接数或者说能同时进行三次握手的最大连接数监听上限)
accept函数(阻塞监听等待客户端建立连接, 成功的话返回一个与客户端成功连接的socket文件描述符)
connect函数(使用现有的socket与服务器建立连接)
三服务器模型和客户端模型的实现
Server服务器的实现
Client客户端的实现 一定义和流程分析
1.定义 定义一个文件描述符指向一个套接字该套接字内部由内核借助两个缓冲区实现在通信过程中 套接字一定是成对出现的一种文件类型伪文件不占用存储空间可进行IO操作可间接看做文件描述符使Socket本身有“插座”的意思在Linux环境下用于表示进程间网络通信的特殊文件类型。本质为内核借助缓冲区形成的伪文件管道, 套接字, 块设备, 字符设备;套接字: 一个fd可以索引读写两个缓冲区; 2.流程分析 socket()创建一个套接字 用fd索引bind()绑定IP和portlisten()设置监听上限同时与Server建立连接数accpet()阻塞监听客户端连接传入一个上面创建的套接字, 传出一个连接的套接字在客户端中的connect()中绑定IP和port并建立连接阻塞 3.网络字节序 小端法pc本地存储 高位存高地址。低位存低地址。 int a 0x12345678
大端法网络存储 高位存低地址。低位存高地址。htonl -- 本地--》 网络 IP 192.168.1.11 -- string -- atoi -- int -- htonl -- 网络字节序
htons -- 本地--》 网络 (port)
ntohl -- 网络--》 本地IP
ntohs -- 网络--》 本地Port 用库函数做网络字节序和主机字节序的转换 #includearpa/inet.h
uint32_t htonl(uint32_t hostlong); //主要针对IP
uint16_t htons(uint16_t hostshort); //主要针对port
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort); 二相关函数
IP地址转换函数inet_pton inet_ntop本地字节序 网络字节序 由于如192.168.45.2这种的IP地址为点分十进制表示需要转化为uint32_t型有现成的函数(IPv4和IPv6都可以转换) //本地字节序string IP --- 网络字节序
int inet_pton(int af, const char *src, void *dst); afAF_INET、AF_INET6src传入IP地址点分十进制dst传出转换后的 网络字节序的 IP地址。 返回值成功 1异常 0 说明src指向的不是一个有效的ip地址。失败-1//网络字节序 --- 本地字节序string IP
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); afAF_INET、AF_INET6src: 网络字节序IP地址dst本地字节序string IPsize dst 的大小。返回值 成功dst、失败NULL socket函数(创建一个套接字) #include sys/socket.hint socket(int domain, int type, int protocol); 创建一个 套接字domain指定使用的协议(IPv4或IPv6)AF_INET 这是大多数用来产生socket的协议使用TCP或UDP来传输用IPv4的地址AF_INET6 与上面类似不过是来用IPv6的地址AF_UNIX 本地协议使用在Unix和Linux系统上一般都是当客户端和服务器在同一台及其上的时候使用type指定数据传输协议(流式或报式)SOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型这个socket是使用TCP来进行传输。SOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的使用UDP来进行它的连接。SOCK_SEQPACKET该协议是双线路的、可靠的连接发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取。SOCK_RAW socket类型提供单一的网络访问这个socket类型使用ICMP公共协议。ping、traceroute使用该协议SOCK_RDM 这个类型是很少使用的在大部分的操作系统上没有实现它是提供给数据链路层使用不保证数据包的顺序指定代表协议(一般默认传0)protocol: 0 流式以TCP为代表;报式以UDP为代表;返回值返回指向新创建的socket的文件描述符成功返回新套接字所对应文件描述符fd失败返回-1并设置errno; bind函数(给socket绑定一个服务器地址结构(IPport)) #include sys/socket.hint bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 给socket绑定一个 地址结构 (IPport)sockfd: socket文件描述符struct sockaddr_in servaddr;addr.sin_family AF_INET;addr.sin_port htons(8888);addr.sin_addr.s_addr htonl(INADDR_ANY);addr: 构造出IP地址加端口号传入参数(struct sockaddr *)addraddrlen: sizeof(addr) 地址结构的大小返回值成功0失败返回-1, 设置errno listen函数(设置最大连接数或者说能同时进行三次握手的最大连接数监听上限) #include sys/types.h /* See NOTES */
#include sys/socket.hint listen(int sockfd, int backlog); //设置同时与服务器建立连接的上限数同时进行3次握手的客户端数量sockfd:socket文件描述符backlog:上限数值。最大值 128排队建立3次握手队列和刚刚建立3次握手队列的链接数和返回值成功0失败-1 errno accept函数(阻塞监听等待客户端建立连接, 成功的话返回一个与客户端成功连接的socket文件描述符) #include sys/types.h /* See NOTES */
#include sys/socket.hint accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);sockfd:socket文件描述符addr:成功与Sever建立连接的那个**客户端**的地址结构;传出参数返回链接客户端地址信息IP地址端口号addrlen:传入传出参数值-结果,传入sizeof(addr)大小函数返回时返回真正接收到地址结构体的大小
socklen_t clit_addr_lensizeof(addr);
入: 传入addr的大小;
出: 客户端addr的实际大小;返回值
成功: 返回能与客户端进行通信的socket对应的文件描述符;
失败: 返回-1并设置errno;//我们的服务器程序结构是这样的
while (1) {cliaddr_len sizeof(cliaddr);connfd accept(listenfd, (struct sockaddr *)cliaddr, cliaddr_len);n read(connfd, buf, MAXLINE);......close(connfd);
}connect函数(使用现有的socket与服务器建立连接) #include sys/types.h /* See NOTES */
#include sys/socket.hint connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);sockdf:socket文件描述符struct sockaddr_in srv_addr; // 服务器地址结构srv_addr.sin_family AF_INET;srv_addr.sin_port 9527 跟服务器bind时设定的 port 完全一致。inet_pton(AF_INET, 服务器的IP地址srv_adrr.sin_addr.s_addr);addr:传入参数指定服务器端地址信息含IP地址和端口号addrlen:传入参数,服务器地址结构的长度sizeof(addr)大小返回值 成功返回0;
失败返回-1并设置errno;如果不使用bind()函数绑定客户端的地址结构, 会采用**隐式绑定**; 三服务器模型和客户端模型的实现
Server服务器的实现 server:1. socket() 创建socket2. bind() 绑定服务器地址结构3. listen() 设置监听上限4. accept() 阻塞监听客户端连接5. read(fd) 读socket获取客户端数据6. 小--大写 toupper()7. write(fd)8. close();代码逻辑 #include stdio.h
#include ctype.h
#include sys/socket.h
#include arpa/inet.h
#include stdlib.h
#include string.h
#include unistd.h
#include errno.h
#include pthread.h#define SERV_PORT 9527 //端口号int main(int argc, char *argv[]){int link_fd0; //建立连接的socket文件描述符int connect_fd0 //用于通信的文件描述符int ret0; //用于检查是否出错char buf[BUFSIZ]; //缓冲区char client_IP[1024] //存入客户端IP字符串int num0; //读出的字节数/*服务器端地址结构*/struct sockaddr_in serv_addr; // 定义服务器地址结构 和 客户端地址结构serv_addr.sin_familyAF_INET; // IPv4serv_addr.sin_porthtons(SERV_PORT); // 转为网络字节序的 端口号serv_addr.sin_addr.s_addrhtonl(INADDR_ANY); // 获取本机任意有效IP/*成功与服务器建立连接的客户端地址结构*/struct sockaddr_in clint_addr;socklen_t clint_addr_lensizeof(clint_addr); // 获取客户端地址结构大小/*1.socket函数:创建用于建立连接的socket,返回的文件描述符存入link_fd*///IPv4按照顺序基于字节流的连接指定代表协议link_fdsocket(AF_INET,SOCK_STREAM,0); if(link_fd-1)sys_err(socket error);/*2.bind函数:绑定服务器端的socket绑定地址结构IPport)*///socket文件描述符link_fd,IP地址加端口号retbind(link_fd,(const struct sockaddr*)serv_addr,sizeof(serv_addr));if(ret-1)sys_err(bind error);/*3.listen函数:设定监听(连接)上线*/retlisten(link_fd,128); if(ret-1)sys_err(listen error);/*4.accept函数:阻塞等待客户端建立连接*///文件描述符,与Sever建立连接的客户端的地址结构,返回真正接收到地址结构体的大小connect_fdaccept(link_fd,( struct sockaddr*)clint_addr,clint_addr_len); if(connect_fd-1)sys_err(accept error);/*建立连接后打印客户端的IP和端口号 获取客户端地址结构*/printf(client IP:%s,client port:%d, //client_IP是前面定义的客户端IP字符串的缓冲区, 大小为1024 inet_ntop(AF_INET,clint_addr.sin_addr.s_addr,client_IP,sizeof(client_IP)), //网络字节序 --- 本地字节序ntohs(clint_addr.sin_port) //根据accept传出参数获取客户端 ip 和 port); /*业务逻辑*/while(1){//5. read(fd) 读socket获取客户端数据numread(connect_fd,buf,sizeof(buf)); // 读客户端数据write(STDOUT_FILENO,buf,num); // 写到屏幕查看//6. 小--大写 toupper()for(i0;inum;i) // 小写 -- 大写buf[i]toupper(buf[i]);//7. write(fd)write(connect_fd,buf,num); // 将大写写回给客户端sleep(1);}//8. close()close(connect_fd);close(link_fd);return 0;
} 测试命令 nc 127.0.0.1 9527 //脑残命令: 向这个服务发送信息并打印回执 Client客户端的实现 client:1. socket() 创建socket2. connect(); 与服务器建立连接3. write() 写数据到 socket4. read() 读转换后的数据5. 显示读取结果6. close() 代码逻辑 #include stdio.h
#include sys/socket.h
#include arpa/inet.h
#include stdlib.h
#include string.h
#include unistd.h
#include errno.h
#include pthread.h#define SERV_PORT 9527/*错误处理函数*/
void sys_err(const char* str){perror(str);exit(1);
}int main(int argc, char *argv[])){int client_fd0;int ret0;int num0;int cnt10;char buf[BUFSIZ];//connect的参数2填入服务器的文件描述符!struct sockaddr_in serv_addr;serv_addr.sin_familyAF_INET;serv_addr.sin_porthtons(SERV_PORT);// 本地字节序string IP --- 网络字节序inet_pton(AF_INET,127.0.0.1,(void*)serv_addr.sin_addr.s_addr);/*1. 创建socket():客户端直接创建用于连接的套接字即可*/client_fdsocket(AF_INET,SOCK_STREAM,0);if(client_fd-1)sys_err(socket error);/*2. connect():将客户端套接字与服务器地址结构连接起来*/retconnect(client_fd,(struct sockaddr*)serv_addr,sizeof(serv_addr));if(ret!0)sys_err(connect error);//业务逻辑while(--cnt){//3. write() 写数据到 socketwrite(client_fd,fuckyou\n,8);//4. read() 读转换后的数据。numread(client_fd,buf,sizeof(buf));//5. 显示读取结果write(STDOUT_FILENO,buf,num);sleep(1);}//6. close()close(client_fd);return 0;
}