大端模式:若将数据的高字节保存在内存的低地址,将数据的低字节保存在内存的高地址;
小端模式:若将数据的高字节保存在内存的高地址,将数据的低字节保存在内存的低地址。
- 网络数据流:大端模式
- 计算机:大端/小端模式
Linux系统中提供了一些用于字节序转换的函数,这些函数存在于函数库arpa/inet.h中,它们的定义如下:
uint32_t htonl(uint32_t hostlong);//主机字节序转换为网络字节序(长整型) uint16_t htons(uint16_t hostshort);//主机字节序转换为网络字节序(短整型) uint32_t ntohl(uint32_t netlong);//网络字节序转换为主机字节序(长整型) uint16_t ntohs(uint16_t netshort);//网络字节序转换为主机字节序(短整型)
- h:主机host;
- n:网络network;
- l:32位长整型;
- s:16位短整型;
- 若主机使用大端模式,则这些函数不做转换,将参数原样返回;
- 若主机采用小端模式,参数的字节顺序才会被修改。
- 常见的IP地址格式类似“192.168.10.1”,这是一个标准的IPv4格式的地址,但这种格式是为了方便用户对其进行操作,若要使计算机能够识别,需先将其转换为二进制格式。
- 如今Linux编程中常用inet_pton()和inet_ntop()来转换IP地址,这两个函数不但能转换IPv4格式的地址in_addr,还能转换IPv6格式的地址in_addr6。
#include int inet_pton(int af, const char *src, void *dst);//先将字符串src转换为af地址族中的网络地址结构,再将转换后的网络地址结构存储到参数dst中,af必须为AF_INET或AF_INET const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);//网络地址转换为字符串3 socket编程实例
【案例 1】编写C/S结构的程序,分别创建服务器和客户端,使用TCP协议实现。
- 客户端:从终端获取一个字符串发送给服务器,然后接收服务器返回的字符串并打印;
- 服务器:接收客户端发来的字符,将每个字符转换为大写再返回给客户端。
tcpclient.c #include#include #include #include #include #include #define MAXLINE 80 #define SERV_PORT 6666 int main(int paraArgc, char *paraArgv[]) { struct sockaddr_in tempServAddr; //定义服务器地址结构体 char tempBuf[MAXLINE]; int tempSockFd, tempDataLen; char *tempStr; if (paraArgc != 2) { fputs("usage: ./client messagen", stderr); exit(1); }//of if tempStr = paraArgv[1]; //创建客户端套接字文件 tempSockFd = socket(AF_INET, SOCK_STREAM, 0); //初始化服务器端口地址 bzero(&tempServAddr, sizeof(tempServAddr)); tempServAddr.sin_family = AF_INET; inet_pton(AF_INET, "127.0.0.1", &tempServAddr.sin_addr); tempServAddr.sin_port = htons(SERV_PORT); //请求链接 connect(tempSockFd, (struct sockaddr *)&tempServAddr, sizeof(tempServAddr)); //发送数据 send(tempSockFd, tempStr, strlen(tempStr), 0); //接收客户端返回的数据 tempDataLen = recv(tempSockFd, tempBuf, MAXLINE, 0); printf("Response from server:n"); //将客户端返回的数据打印到终端 write(STDOUT_FILENO, tempBuf, tempDataLen); //关闭连接 close(tempSockFd); return 0; }//of main tcpserver.c #include #include #include #include #include #include #include #define MAXLINE 80 //最大数据长度 #define SERV_PORT 6666 //服务器端口号 int main(void) { struct sockaddr_in tempServAddr, tempCliAddr; //定义服务器与客户端地址结构体 socklen_t tempCliAddrLen; //客户端地址长度 int tempListenFd, tempConnFd; char tempBuf[MAXLINE]; char tempStr[INET_ADDRSTRLEN]; int i, tempDataLen; //创建服务器端套接字文件 tempListenFd = socket(AF_INET, SOCK_STREAM, 0); //初始化服务器端口地址 bzero(&tempServAddr, sizeof(tempServAddr)); //将服务器端口地址清零 tempServAddr.sin_family = AF_INET; tempServAddr.sin_addr.s_addr = htonl(INADDR_ANY); tempServAddr.sin_port = htons(SERV_PORT); //将套接字文件与服务器端口地址绑定 bind(tempListenFd , (struct sockaddr *)&tempServAddr, sizeof(tempServAddr)); //监听,并设置最大连接数为20 listen(tempListenFd , 20); printf("Accepting connections ...n"); //接收客户端数据,并处理请求 while (1) { tempCliAddrLen= sizeof(tempCliAddr); tempConnFd = accept(tempListenFd, (struct sockaddr *)&tempCliAddr, &tempCliAddrLen); tempDataLen = recv(tempConnFd, tempBuf, MAXLINE, 0); printf("received from %s at PORT %dn", inet_ntop(AF_INET, &tempCliAddr.sin_addr, tempStr, sizeof(tempStr)), ntohs(tempCliAddr.sin_port)); for (i = 0; i < tempDataLen; i++){ tempBuf[i] = toupper(tempBuf[i]); }//of for i send(tempConnFd, tempBuf, tempDataLen, 0); //关闭连接 close(connfd); }//of while return 0; }//of main
【案例2】编写C/S结构的程序,分别创建服务器和客户端,使用UDP协议实现。
- 客户端:从终端获取一个字符串发送给服务器,然后接收服务器返回的字符串并打印;
- 服务器:接收客户端发来的字符,将每个字符转换为大写再返回给客户端。
udpclient.c #include#include #include #include #include #include #include #define MAXLINE 80 #define SERV_PORT 6666 int main(int paraArgc, char *paraArgv[]){ struct sockaddr_in tempServAddr; int tempSockFd, tempDataLen; char tempBuf[MAXLINE]; tempSockFd = socket(AF_INET, SOCK_DGRAM, 0); bzero(&tempServAddr, sizeof(tempServAddr)); tempServAddr.sin_family = AF_INET; inet_pton(AF_INET, "127.0.0.1", &tempServAddr.sin_addr); tempServAddr.sin_port = htons(SERV_PORT); //发送数据到客户端 while (fgets(tempBuf, MAXLINE, stdin) != NULL) { tempDataLen = sendto(tempSockFd, tempBuf, strlen(tempBuf), 0, (struct sockaddr *)&tempServAddr, sizeof(tempServAddr)); if (tempDataLen == -1) { perror("sendto error"); }//of if //接收客户端返回的数据 tempDataLen = recvfrom(tempSockFd, tempBuf, MAXLINE, 0, NULL, 0); if (tempDataLen == -1){ perror("recvfrom error"); }//of if //将接收到的数据打印到终端 send(STDOUT_FILENO, tempBuf, tempDataLen , 0); }//of while close(tempSockFd); return 0; }//of main udpserver.c #include #include #include #include #include #include #include #define MAXLINE 80 //最大数据长度 #define SERV_PORT 6666 //服务器端口号 int main(void) { struct sockaddr_in tempServAddr, tempCliAddr; //定义服务器与客户端地址结构体 socklen_t tempCliAddrLen; //客户端地址长度 int tempSockFd; //服务器socket文件描述符 char tempBuf[MAXLINE]; char tempStr[INET_ADDRSTRLEN]; int i, tempDataLen; tempSockFd = socket(AF_INET, SOCK_DGRAM, 0);//创建服务器端套接字文件 //初始化服务器端口地址 bzero(&tempServAddr, sizeof(tempServAddr)); //地址结构体清零 tempServAddr.sin_family = AF_INET; //指定协议族 tempServAddr.sin_addr.s_addr = htonl(INADDR_ANY); tempServAddr.sin_port = htons(SERV_PORT); //指定端口号 //绑定服务器端口地址 bind(tempSockFd, (struct sockaddr *)&tempServAddr, sizeof(tempServAddr)); printf("Accepting connections ...n"); //数据传输 while (1) { tempCliAddrLen = sizeof(tempCliAddr); //接收数据 tempDataLen = recvfrom(tempSockFd, tempBuf, MAXLINE, 0, (struct sockaddr*)&tempCliAddr, &tempCliAddrLen); if (tempDataLen == -1){ perror("recvfrom error"); }//of if printf("received from %s at PORT %dn", inet_ntop(AF_INET, &tempCliAddr.sin_addr, tempStr, sizeof(tempStr)), ntohs(tempCliAddr.sin_port)); //服务器端操作,小写转大写 for (i = 0; i < tempDataLen; i++){ buf[i] = toupper(buf[i]); }//of for i tempDataLen = sendto(tempSockFd, tempBuf, tempDataLen, 0, (struct sockaddr *)&tempCliAddr, sizeof(tempCliAddr)); if (tempDataLen == -1){ perror("sendto error"); }//of if }//of while close(tempSockFd); return 0; }//of main



