日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Socket通信之操作系统的字节序和位数

發(fā)布時(shí)間:2023/11/27 生活经验 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Socket通信之操作系统的字节序和位数 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

關(guān)于Socket通信過程中字節(jié)序

在網(wǎng)絡(luò)編程里,網(wǎng)絡(luò)字節(jié)序是big-endian的,而大部分的PC的系統(tǒng)都是X86處理器系列,X86采用的是little-endian,所以需要將網(wǎng)絡(luò)數(shù)據(jù)流轉(zhuǎn)換成本地?cái)?shù)據(jù)流的話,需要進(jìn)行字節(jié)序的轉(zhuǎn)換。

標(biāo)準(zhǔn)庫(kù)里提供了hlton()和nthl()兩個(gè)函數(shù)來支持轉(zhuǎn)換。

hston(unsigned short), hlton(unsigned long) ?將本地字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序

ntohl(unsigned long), ntohs(unsigned short) ?將網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換為本地字節(jié)序

但是對(duì)于64位的整數(shù)進(jìn)行轉(zhuǎn)換,標(biāo)準(zhǔn)庫(kù)并沒有提供相應(yīng)的轉(zhuǎn)換函數(shù)。

關(guān)于本系統(tǒng)是Big-endian還是Little-endian存儲(chǔ),可以寫一個(gè)簡(jiǎn)單函數(shù)進(jìn)行判斷:

#include<stdio.h>
int main(){int num = 0x1234;int* p = &num;if(*((char*)p) == 0x12){printf("Big-endian\n");}else{printf("Little-endian\n");}return 0;
}

另外,關(guān)于socket通信過程中客戶端和服務(wù)端操作系統(tǒng)位數(shù)的問題,本人在Vmware中開啟了三個(gè)Ubuntu(兩個(gè)為32位操作系統(tǒng),一個(gè)為64位操作系統(tǒng),皆為小端存儲(chǔ)),以一個(gè)32位系統(tǒng)運(yùn)行socket通信的客戶端,另外兩個(gè)設(shè)置為服務(wù)端,通過修改客戶端的訪問目標(biāo)ip地址觀察不同位系統(tǒng)socket通信結(jié)果,發(fā)現(xiàn)32to32,一切正常可以運(yùn)行,程序命令行傳入?yún)?shù)可以順利達(dá)到服務(wù)端經(jīng)服務(wù)端數(shù)據(jù)處理函數(shù)處理之后返回至客戶端并打印出來,期間在服務(wù)端打印出客戶端傳送過來的數(shù)據(jù)并打印客戶端的地址、端口信息。

但在32to64通信過程中,服務(wù)端顯示亂碼,且不能正常返回處理后的數(shù)據(jù)。

查閱資料:在32位機(jī)器和64機(jī)器中int類型都占用4個(gè)字節(jié)。編譯器可以根據(jù)自身硬件來選擇合適的大小,但是需要滿足約束:short和int型至少為16位,long型至少為32位,并且short型長(zhǎng)度不能超過int型,而int型不能超過long型。?
這即是說各個(gè)類型的變量長(zhǎng)度是由編譯器來決定的,而當(dāng)前主流的編譯器中一般是32位機(jī)器和64位機(jī)器中int型都是4個(gè)字節(jié),總體而言,最大的不同點(diǎn)就是在long型和指針類型長(zhǎng)度不一樣,對(duì)于指針而言,64位機(jī)器可以尋址2^64,每個(gè)內(nèi)存地址長(zhǎng)度為64位,即8字節(jié)。

服務(wù)端程序:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <ctype.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define MAX_LINE 100
/* 處理函數(shù),用于將大寫字符轉(zhuǎn)換為小寫字符。參數(shù)為需要轉(zhuǎn)換的字符串 */
void my_fun(char * p)
{if(p == NULL)				 /* 空串 */return;for (; *p != '\0'; p++)if(*p >= 'A' && *p <= 'Z') /* 判斷字符并進(jìn)行轉(zhuǎn)換,也可以使用庫(kù)函數(shù) */*p = *p -'A' + 'a';
}
int main(void)
{struct sockaddr_in sin;struct sockaddr_in cin;int l_fd;int c_fd;socklen_t len;char buf[MAX_LINE];					/* 存儲(chǔ)傳送內(nèi)容的緩沖區(qū) */char addr_p[INET_ADDRSTRLEN];		/* 存儲(chǔ)客戶端地址的緩沖區(qū) */int port = 8000;					/* 端口號(hào),使用8000 */int n;								/* 讀寫字節(jié)數(shù) */bzero(&sin, sizeof(sin));			/* 清空地址結(jié)構(gòu) */sin.sin_family = AF_INET;			/* 使用IPv4通信域 */sin.sin_addr.s_addr = INADDR_ANY;	/* 服務(wù)器可以接受任意地址 */sin.sin_port = htons(port);		/* 端口號(hào)轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序 */l_fd = socket(AF_INET, SOCK_STREAM, 0); /* 創(chuàng)立套接字,使用TCP協(xié)議 */bind(l_fd, (struct sockaddr*) &sin, sizeof(sin)); /* 將地址和套接字綁定 */listen(l_fd, 10);						/* 開始監(jiān)聽連接請(qǐng)求 */printf("waiting ...\n");while(1){/* 服務(wù)器程序多半是死循環(huán) *//* 接受連接請(qǐng)求,從此函數(shù)中返回后就可以開始通信了 */c_fd = accept(l_fd, (struct sockaddr*) &cin, &len); n = read(c_fd, buf, MAX_LINE);	/* 讀取客戶端傳來的信息 *///inet_ntop(AF_INET, &cin.sin_addr, addr_p, sizeof(addr_p));/* 將客戶端地址轉(zhuǎn)換為字符串 *///printf("client IP is %s, port is %d\n", addr_p, ntohs(cin.sin_port)); 											/* 打印客戶端地址和端口號(hào) */printf("content is : %s\n", buf);	/* 打印客戶端發(fā)送過來的字符串 */my_fun(buf);						/* 調(diào)用大小寫轉(zhuǎn)換函數(shù) */write(c_fd, buf, n);				/* 將轉(zhuǎn)換后的字串發(fā)給客戶端 */close(c_fd);			/* 通信結(jié)束,關(guān)閉套接字,準(zhǔn)備下一次通信 */}if(close(l_fd) == -1){		/* 通信結(jié)束,關(guān)閉套接字,準(zhǔn)備下一次通信 */perror("fail to close");exit(1);}return 0; /* 不應(yīng)該執(zhí)行到這里 */
}

?客戶端程序:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#define MAX_LINE 100int main(void)
{struct sockaddr_in sin;char msg[100];int l_fd;char buf[MAX_LINE];                                     /* 存儲(chǔ)傳送內(nèi)容的緩沖區(qū) */int port = 8000;                                       /* 端口號(hào),使用8000 */bzero(&sin, sizeof(sin));                       /* 清空地址結(jié)構(gòu) */sin.sin_family = AF_INET;                       /* 使用IPv4通信域 */inet_pton(AF_INET,"10.17.38.98", &sin.sin_addr);sin.sin_port = htons(port);             /* 端口號(hào)轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序 */l_fd = socket(AF_INET, SOCK_STREAM, 0); /* 創(chuàng)立套接字,使用TCP協(xié)議 */connect(l_fd, (const struct sockaddr*)&sin, sizeof(sin));printf("Input Message:\n");scanf("%s", msg);write(l_fd, msg, strlen(msg)+1);sleep(5); //延時(shí)讀取read(l_fd, buf, MAX_LINE);printf("Receive messaege from server: %s\n", buf);//close(l_fd);if(close(l_fd) == -1){          /* 通信結(jié)束,關(guān)閉套接字,準(zhǔn)備下一次通信 */perror("Fail to close !");exit(1);}return 0;
}

對(duì)64位服務(wù)端的server.c程序屏蔽掉客戶端IP、端口獲取并打印的相關(guān)代碼段,此時(shí)服務(wù)端、客戶端均能能夠正常運(yùn)行。因此,在char型命令行參數(shù)傳遞過程中是沒有問題的,32位和64位操作系統(tǒng)的主要區(qū)別在于指針以及結(jié)構(gòu)體(內(nèi)存對(duì)齊位數(shù)不同),而accept()的第二個(gè)參數(shù)是客戶端的地址結(jié)構(gòu),由客戶端的connect()函數(shù)發(fā)送給服務(wù)端,在這過程中存在位數(shù)不匹配的問題,因此不能進(jìn)行正常通信。

另,根據(jù)上述原理,可以聲明一個(gè)空類型指針用來判斷系統(tǒng)的位數(shù)。

#include<iostream>int main(){void* p;if(sizeof(p)==4){std::cout << "This is a 32-bit machine."  << std::endl;}else std::cout << "This is a 64-bit machine." << std::endl;return 0;
}

在32位和64位系統(tǒng)測(cè)試結(jié)果如下:

?

總結(jié)

以上是生活随笔為你收集整理的Socket通信之操作系统的字节序和位数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。