目錄linux
32位置機器一次性能裝載4字節。那麼四字節在內存的順序影響它被累加器裝載成的整數的值。主要分爲大端和小端。c++
大端字節序是一個整數高位字節(23~31bit)存在內存的低處,低字節(0~7 bit) 存儲在內存的高地址處。小端相反。編程
現代PC大可能是小端序。小端就稱爲主機字節序。JVM採用大端(網絡字節序)。下面是檢測大端小段的案例數組
個人linux機子是小端序了。。。網絡
union { short value; char union_bytes[sizeof( short ) ]; } test; test.value = 0x0102; printf("%d %d\n", test.union_bytes[0], test.union_bytes[1]); if(test.union_bytes[0] == 1 && test.union_bytes[1] == 2) { puts("大端序"); } else if(test.union_bytes[0] == 2 && test.union_bytes[1] == 1) { puts("小端序"); } else { puts("未知"); }
linux下提供了四個函數來完成主機字節序和網絡字節序的轉換。dom
#include <netinet/in.h> unsigned long int htonl(unsigned long int hostlong); unsigned short int htons(unsigned short int hostshort); unsigned long int ntohl(unsigned long int netlong); unsigned short int ntohs(unsigned short int netshort);
例如:host to network long => htonlsocket
服務端:函數
#include <bits/stdc++.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <unistd.h> #include <errno.h> #define BUF_SIZE 1024 int main(int argc, char *argv[]) { if ( argc <= 2 ) { printf("usage: %s ip_address port_number\n", basename( argv[0] )); return 1; } const char* ip = argv[1]; int port = atoi( argv[2] ); // =================================================================================================================== // 建立套接字 //建立地址的結構體 struct sockaddr_in address; // <netinet/in.h> //* Structure describing an Internet socket address. */ // struct sockaddr_in // { // __SOCKADDR_COMMON (sin_); // in_port_t sin_port; /* Port number. */ // struct in_addr sin_addr; /* Internet address. */ // // /* Pad to size of `struct sockaddr'. */ // unsigned char sin_zero[sizeof (struct sockaddr) - // __SOCKADDR_COMMON_SIZE - // sizeof (in_port_t) - // sizeof (struct in_addr)]; // }; bzero(&address, sizeof( address )); // <string.h> /* Set N bytes of S to 0. */ // extern void bzero (void *__s, size_t __n) __THROW __nonnull ((1)); // 裏面的sin_zero數組一般清零,因此這麼寫 address.sin_family = AF_INET; // AF_INET表明IPV4地址族,PF_INET是對應的協議族,宏定義的值是同樣的,理論上能夠混用 inet_pton(AF_INET, ip, &address.sin_addr); // <arpa/inet.h> // // extern int inet_pton (int __af, const char *__restrict __cp, // void *__restrict __buf) __THROW; // // /* Convert from presentation format of an Internet number in buffer // starting at CP to the binary network format and store result for // interface type AF in buffer starting at BUF. */ address.sin_port = htons( port ); // 大端字節序和小段字節序的轉換 <netinet/in.h> int sock = socket(PF_INET, SOCK_STREAM, 0); //建立套接字 <sys/socket.h> assert( sock >= 0 ); //* Create a new socket of type TYPE in domain DOMAIN, using // protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically. // Returns a file descriptor for the new socket, or -1 for errors. */ // extern int socket (int __domain, int __type, int __protocol) __THROW; // domain: 說明系統底層的協議族,對於TCP/IP 而言,改參數設置爲PF_INET(IPV4), // PF_INET6(IPV6), UNIX本地域協議簇,改參數設置爲 PF_UNIX // type: 服務類型 SOCK_STREAM(流服務),SOCK_UGRAM(數據報) // 對於TCP,SOCK_STREAM 表示TCP, SOCK_DGRAM 表示 // protocol: 在前面的協議前提下的可選參數,通常給0就好 // =================================================================================================================== // 命名socket int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address )); assert( ret != -1 ); // /* Give the socket FD the local address ADDR (which is LEN bytes long). */ // extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) // __THROW; // sock就是剛剛socket的返回值。能夠理解爲端口和IP綁定。 ret = listen( sock, 5 ); // 開始監聽。 assert( ret != -1 ); // /* Prepare to accept connections on socket FD. // N connection requests will be queued before further requests are refused. // Returns 0 on success, -1 for errors. */ // extern int listen (int __fd, int __n) __THROW; // 第二個參數是處於徹底鏈接狀態(ESTABLISHED)的 socket上線。 struct sockaddr_in client; socklen_t client_addrlength = sizeof( client ); // types.h 是個 unsigned int int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength); // This function is a cancellation point and therefore not marked with // __THROW. */ // extern int accept (int __fd, __SOCKADDR_ARG __addr, // socklen_t *__restrict __addr_len); // if(connfd < 0) { printf("errno is: %d\n", errno); } else { char buffer[ BUF_SIZE ]; memset( buffer, '\0', BUF_SIZE ); ret = recv( connfd, buffer, BUF_SIZE - 1, 0 ); printf("[%d: %s]\n", ret, buffer); memset( buffer, '\0', BUF_SIZE ); ret = recv( connfd, buffer, BUF_SIZE - 1, MSG_OOB ); printf("[%d: %s]\n", ret, buffer); memset( buffer, '\0', BUF_SIZE ); ret = recv( connfd, buffer, BUF_SIZE - 1, 0 ); printf("[%d: %s]\n", ret, buffer); close( connfd ); } close( sock ); return 0; }
客戶端:性能
#include <bits/stdc++.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <unistd.h> int main(int argc, char *argv[]) { if(argc <= 2) { printf("usage: %s ip_address port_number\n", basename( argv[0] )); // basename : // Return the file name within directory of FILENAME. We don't // declare the function if the `basename' macro is available (defined // in <libgen.h>) which makes the XPG version of this function // available. return 1; } const char* ip = argv[1]; int port = atoi( argv[2] ); printf("ip = %s port = %d\n", ip, port); struct sockaddr_in server_address; bzero(&server_address, sizeof( server_address )); server_address.sin_family = AF_INET; //#define PF_INET 2 //IP protocol family. // PF_INET equal AF_INET inet_pton( AF_INET, ip, &server_address.sin_addr ); server_address.sin_port = htons( port ); int sockfd = socket( PF_INET, SOCK_STREAM, 0 ); assert( sockfd >= 0 ); if( connect( sockfd, ( struct sockaddr* )&server_address, sizeof( server_address ) ) < 0 ) { printf("connection failed\n"); } else { const char *oob_data = "abc"; const char *normal_data = "123"; send(sockfd, normal_data, strlen(normal_data), 0); send(sockfd, oob_data, strlen(oob_data), MSG_OOB); send(sockfd, normal_data, strlen(normal_data), 0); } close(sockfd); return 0; }