网络编程-socket
生活随笔
收集整理的這篇文章主要介紹了
网络编程-socket
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
看到這篇文章寫得挺清楚 就貼過來了
http://8-1.myrice.com/study/linux/linux.htm
*******************************************************
好了,我們開始吧,Socket,你一定很熟悉Socket這個詞,無論是在windows還是linux,
只要你要telnet主機,或是用ftp上傳文件到服務器,又或是用瀏覽器看網頁,就一定會
用到他。
如果你是新手,你到這里來,已經走到了socket編程的第一步。假設你已經有C語言編
程的基礎,我不想在這里多談C語言
----------------------------------
既使你知道Socket這個詞,既使你常聽到人們談到“Socket”,而你卻不知道其確切含義
。其實他是使用文件描述符 和其他程序通訊的方式。
OK,在UNIX里,所有的東西都是文件,你的CDROM是文件,你的顯示器是文件,
你的硬盤也是文件你的。。。也是文件。。。所以,你想和網絡上其他程序通信的時
候就要通過文件描述符。那是真的,請你相信,我決不騙你。
現在你或許會想:我該怎么樣得到網絡通訊的文件描述符呢?你就要用到系統調用
socket(),他返回套接口文件描述符,然后你可以把這個文件描述符當作普通的文件來
操作,不過最好使用send()和recv(),這樣比較好點,好處以后再說!
在internet上有多種套接口,不用驚奇,也不要感到害怕,因為常用的套接口只有兩種
,那就是流式套接品和數據報套接口,而我這里要講的只是流式套接口,對于數據報
套
接口只作簡單的介紹。如果理解了流式套接口,其他的也就簡單了。因為他們都是套接
口!
流式套接口可以提供可靠的雙向通訊數據流,他們也是無錯誤的傳遞,在TCP里有自已
的錯誤控制。
使用流式套接口的例子很多,至少你的瀏覽器就在用!因為瀏覽其實就是telnet到主機的
80端口get頁面,然后你可愛的netscapt或ie就可以看到網頁html的內容了!
因為流式套接口使用的是傳輸控制協議(TCP)所以數據可以按順序,到達并且不會出
錯。或許你聽說過TCP/IP,這里的IP指的是Internet協議,他用來處理Internet路由。
而數據報套接口可以提供更快的傳輸速率,但卻是不可靠的。舉個例子,你傳送一組數
據123456789,可能到達時,他的次序已經亂了,可能是987456321了不過你可以放心,
IP路由會為你處理這個問題,他不使用TCP,而是使用UDP,一種叫“用戶數據包協議”
的怪異東東,而且怪異到不用維持一個連接就能發送數據。只要數據包里構造一個IP頭
,IP頭里包括你要發送到的目的地信息。
“STOP!”你也許會被那些怪異的事搞的發瘋,或許你還是無法理解什么是套接口,好吧
,讓我們從一個程序開始吧!
Linux Socket 網絡編程(二)
好了,現在我來解釋一個前次的程序;
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
這些是必要和頭文件
#define PORT 4567
#define BUFSIZE 512
常量定義,假設端口為4567,緩沖為512字節
int main(int argc,char** argv)
這就不用我解釋了吧:)如果真不知道,去翻翻有關C語言的書吧!
{
int socketf,n;
char buf[BUFSIZE];
struct sockaddr_in server;
有必要解釋一下sockaddr_in
這是一個internet 套接口結構,
struct in_addr {
in_addr_t s_addr; /* 32位IPV4地址 */
};
struct sockaddr_in {
short int sin_family; /* 地址族 */
unsigned short int sin_port; /* 端口 */
struct in_addr sin_addr; /* internet地址(32位IPV4) */
unsigned char sin_zero[8]; /* 不知道什么用,反正沒用到過 */
};
對于sin_family,我們一般都填AF_INET,當然還有其他的,我們一般現在用的都還是
IPV4,如果你要用IPV6,這個就是AF_INET6啦!只是多加了一個6,就把32位IP地址變
成了128位,這個世界真是神奇(當然你還要做很多事)
sin_port是你的端口號,看到了吧,是16位的,所以端口號不會大于
0xffff啦;要注意的是
要把它轉換成網絡字節序,這就要用到以下四個函數了:
htons()
htonl()
ntohs()
ntohl()
是不是有些眼花了,這四個函數好像很像啊!對了,其實他們都是做同樣的事,只是分
工不同
htons把16位本地字節序轉換成16位網絡字節序,ntohs剛好相反
htonl把32位本地字節序轉換成32位網絡字節序,ntohl剛好相反
告訴你們一個訣竅,這里的h代表host,n代表network,s代表short(16位),l代表long(32位)
這樣是不是好記了點?只要你懂得英語里"to"這個單詞的含義就行了!
好了,看看我們的IP地址,是in_addr結構.再深入一步看in_addr結構,
里面有
in_addr_t s_addr;
這里的in_addr_t其實就是unsigned int,不要被它的樣子嚇壞,其實它很可愛:)
所以我們填寫IP地址的時候就要
...
struct sockaddr_in server;
...
server.sin_addr.s_addr=inet_addr("192.168.0.1");
inet_addr()可以把你的點分十進制IP地址變為計算機認識的IP地址;
仔細的人可能以經看出,我這里沒有用htonl(),那是因為inet_addr已經把IP地址轉換為
網絡字節序了!真是聰明!噢,我指的是inet_addr()很聰明!
至于sin_zero[8];一般都是把它清空為0,不過為了方便,在初始化的時候把整個結構清
空;我們可以用bzero()和memset()不過用bzero更方便點,memset()功能更強大點,不過在
這里這兩個都一樣,我們就用bzero了!
OK,整個結構都說完了,現在回到我們的程序去吧!
if(argc!=2)
{
printf("%s","IP address error");
exit(-1);
}
當然,你不輸入IP地址,你的程序當然不知道要連接到哪兒去啊!
if((socketf=socket(AF_INET,SOCK_STREAM,0)<=0)
{
printf("%s","socket error");
exit(-1);
}
這又是什么?socket()?哦,我忘了解釋套接口描述字了!
還記得我以前說過,在UNIX里,什么東西都是文件嗎?對,套接口也是文件,所以
也要用文件描述符,只是這里是套接口描述符而已,其實都差不多。
上面socketf=socket(AF_INET,SOCK_STREAM,0)就是為了得到這個套接口描述符。
AF_INET是必須的,如果用到的是IPV6這里就是AF_INET6了,SOCK_STREAM指明是
流式套接口,而不是數據報套接口(其實套接口的種類遠不指這些,只是不想讓大家多傷
腦細胞而已)。最后一個一定要填0,可能是為以后著想的吧!
bzero(&server,sizeof(server));
還記得這個bzero嗎?我在前面說過的!對,把結構清空!為了方便,我們把整個結
構清空了!
server.sin_family = AF_INET;
server.port = htons(PORT);
server.sin_addr.s_addr=inet_addr(argv[1]);
好,填寫套接口結構。看清最后一行了嗎?怎么填IP地址。不過這里有個錯誤,因
為inet_addr在出錯時返回-1,-1是什么?記得0xffffffff嗎?這是什么?把它翻成點分
十進制吧,那就是255.255.255.255,這就是internet廣播地址。0xffffffff第一位是符號
位,所以也是-1。真是歷害,一出錯就發廣播了,是不是怕天下人不知道啊?
if(connetc(socketf,(struct sockaddr *)&server,sizeof(server))<0)
{
printf("%s","connetc error");
exit(-1);
}
得到了socketf,我們就可以連接了,這就要用到connetc了!
是不是該解釋一個這個函數了?OK!第一個參數是套接口描述字,就是要連接上哪
個套接口。第二個是一個套接口結構地址指針,我們這里是server,當然要數據轉換了,
因為一個是sockaddr,一個是sockaddr_in,雖然這兩個其實差不多,不過轉換還是必要的。
還是不明白?算了,還是好人做到底,把sockaddr這個結構也解釋一下吧!
struct sockaddr {
unsigned short sa_family; /* 地族,當然也是 AF_xxx */
char sa_data[14]; /* 14 bytes 協議地址 */
};
啊,和我們的sockaddr_in差不多嘛,我沒騙你吧,只是把sa_data[14]分得更小更多我們
把sockaddr_in里除了sa_family外其他的加起來,也剛好是14
bytes耶!如果有興趣,
你也可以用sockaddr代替sockaddr_in,當然在實際編程中恐怕。。。很少或幾乎是沒
有人會這樣做的吧!
好了,讓我們回到connect吧,還有最后一個參數,說明要連接對向的大小,我們這
里是server大小~!
當然,如果連接出錯我們就exit(-1);閃人嘍~!
if(recv(socketf,buf,BUFSIZE,0)<0)
{
prinft("%s","recever error");
exit(-1);
}
else
printf("%s",buf);
recv(),接收數據,我這里就不發送了,從socketf接受BUFSIZE個字節的數據到buf里去;
close(socketf);
文件用完要關閉,套接口也是一樣,要close(socketf);
}
最后不要忘了關門
http://8-1.myrice.com/study/linux/linux.htm
*******************************************************
好了,我們開始吧,Socket,你一定很熟悉Socket這個詞,無論是在windows還是linux,
只要你要telnet主機,或是用ftp上傳文件到服務器,又或是用瀏覽器看網頁,就一定會
用到他。
如果你是新手,你到這里來,已經走到了socket編程的第一步。假設你已經有C語言編
程的基礎,我不想在這里多談C語言
----------------------------------
既使你知道Socket這個詞,既使你常聽到人們談到“Socket”,而你卻不知道其確切含義
。其實他是使用文件描述符 和其他程序通訊的方式。
OK,在UNIX里,所有的東西都是文件,你的CDROM是文件,你的顯示器是文件,
你的硬盤也是文件你的。。。也是文件。。。所以,你想和網絡上其他程序通信的時
候就要通過文件描述符。那是真的,請你相信,我決不騙你。
現在你或許會想:我該怎么樣得到網絡通訊的文件描述符呢?你就要用到系統調用
socket(),他返回套接口文件描述符,然后你可以把這個文件描述符當作普通的文件來
操作,不過最好使用send()和recv(),這樣比較好點,好處以后再說!
在internet上有多種套接口,不用驚奇,也不要感到害怕,因為常用的套接口只有兩種
,那就是流式套接品和數據報套接口,而我這里要講的只是流式套接口,對于數據報
套
接口只作簡單的介紹。如果理解了流式套接口,其他的也就簡單了。因為他們都是套接
口!
流式套接口可以提供可靠的雙向通訊數據流,他們也是無錯誤的傳遞,在TCP里有自已
的錯誤控制。
使用流式套接口的例子很多,至少你的瀏覽器就在用!因為瀏覽其實就是telnet到主機的
80端口get頁面,然后你可愛的netscapt或ie就可以看到網頁html的內容了!
因為流式套接口使用的是傳輸控制協議(TCP)所以數據可以按順序,到達并且不會出
錯。或許你聽說過TCP/IP,這里的IP指的是Internet協議,他用來處理Internet路由。
而數據報套接口可以提供更快的傳輸速率,但卻是不可靠的。舉個例子,你傳送一組數
據123456789,可能到達時,他的次序已經亂了,可能是987456321了不過你可以放心,
IP路由會為你處理這個問題,他不使用TCP,而是使用UDP,一種叫“用戶數據包協議”
的怪異東東,而且怪異到不用維持一個連接就能發送數據。只要數據包里構造一個IP頭
,IP頭里包括你要發送到的目的地信息。
“STOP!”你也許會被那些怪異的事搞的發瘋,或許你還是無法理解什么是套接口,好吧
,讓我們從一個程序開始吧!
Linux Socket 網絡編程(二)
好了,現在我來解釋一個前次的程序;
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
這些是必要和頭文件
#define PORT 4567
#define BUFSIZE 512
常量定義,假設端口為4567,緩沖為512字節
int main(int argc,char** argv)
這就不用我解釋了吧:)如果真不知道,去翻翻有關C語言的書吧!
{
int socketf,n;
char buf[BUFSIZE];
struct sockaddr_in server;
有必要解釋一下sockaddr_in
這是一個internet 套接口結構,
struct in_addr {
in_addr_t s_addr; /* 32位IPV4地址 */
};
struct sockaddr_in {
short int sin_family; /* 地址族 */
unsigned short int sin_port; /* 端口 */
struct in_addr sin_addr; /* internet地址(32位IPV4) */
unsigned char sin_zero[8]; /* 不知道什么用,反正沒用到過 */
};
對于sin_family,我們一般都填AF_INET,當然還有其他的,我們一般現在用的都還是
IPV4,如果你要用IPV6,這個就是AF_INET6啦!只是多加了一個6,就把32位IP地址變
成了128位,這個世界真是神奇(當然你還要做很多事)
sin_port是你的端口號,看到了吧,是16位的,所以端口號不會大于
0xffff啦;要注意的是
要把它轉換成網絡字節序,這就要用到以下四個函數了:
htons()
htonl()
ntohs()
ntohl()
是不是有些眼花了,這四個函數好像很像啊!對了,其實他們都是做同樣的事,只是分
工不同
htons把16位本地字節序轉換成16位網絡字節序,ntohs剛好相反
htonl把32位本地字節序轉換成32位網絡字節序,ntohl剛好相反
告訴你們一個訣竅,這里的h代表host,n代表network,s代表short(16位),l代表long(32位)
這樣是不是好記了點?只要你懂得英語里"to"這個單詞的含義就行了!
好了,看看我們的IP地址,是in_addr結構.再深入一步看in_addr結構,
里面有
in_addr_t s_addr;
這里的in_addr_t其實就是unsigned int,不要被它的樣子嚇壞,其實它很可愛:)
所以我們填寫IP地址的時候就要
...
struct sockaddr_in server;
...
server.sin_addr.s_addr=inet_addr("192.168.0.1");
inet_addr()可以把你的點分十進制IP地址變為計算機認識的IP地址;
仔細的人可能以經看出,我這里沒有用htonl(),那是因為inet_addr已經把IP地址轉換為
網絡字節序了!真是聰明!噢,我指的是inet_addr()很聰明!
至于sin_zero[8];一般都是把它清空為0,不過為了方便,在初始化的時候把整個結構清
空;我們可以用bzero()和memset()不過用bzero更方便點,memset()功能更強大點,不過在
這里這兩個都一樣,我們就用bzero了!
OK,整個結構都說完了,現在回到我們的程序去吧!
if(argc!=2)
{
printf("%s","IP address error");
exit(-1);
}
當然,你不輸入IP地址,你的程序當然不知道要連接到哪兒去啊!
if((socketf=socket(AF_INET,SOCK_STREAM,0)<=0)
{
printf("%s","socket error");
exit(-1);
}
這又是什么?socket()?哦,我忘了解釋套接口描述字了!
還記得我以前說過,在UNIX里,什么東西都是文件嗎?對,套接口也是文件,所以
也要用文件描述符,只是這里是套接口描述符而已,其實都差不多。
上面socketf=socket(AF_INET,SOCK_STREAM,0)就是為了得到這個套接口描述符。
AF_INET是必須的,如果用到的是IPV6這里就是AF_INET6了,SOCK_STREAM指明是
流式套接口,而不是數據報套接口(其實套接口的種類遠不指這些,只是不想讓大家多傷
腦細胞而已)。最后一個一定要填0,可能是為以后著想的吧!
bzero(&server,sizeof(server));
還記得這個bzero嗎?我在前面說過的!對,把結構清空!為了方便,我們把整個結
構清空了!
server.sin_family = AF_INET;
server.port = htons(PORT);
server.sin_addr.s_addr=inet_addr(argv[1]);
好,填寫套接口結構。看清最后一行了嗎?怎么填IP地址。不過這里有個錯誤,因
為inet_addr在出錯時返回-1,-1是什么?記得0xffffffff嗎?這是什么?把它翻成點分
十進制吧,那就是255.255.255.255,這就是internet廣播地址。0xffffffff第一位是符號
位,所以也是-1。真是歷害,一出錯就發廣播了,是不是怕天下人不知道啊?
if(connetc(socketf,(struct sockaddr *)&server,sizeof(server))<0)
{
printf("%s","connetc error");
exit(-1);
}
得到了socketf,我們就可以連接了,這就要用到connetc了!
是不是該解釋一個這個函數了?OK!第一個參數是套接口描述字,就是要連接上哪
個套接口。第二個是一個套接口結構地址指針,我們這里是server,當然要數據轉換了,
因為一個是sockaddr,一個是sockaddr_in,雖然這兩個其實差不多,不過轉換還是必要的。
還是不明白?算了,還是好人做到底,把sockaddr這個結構也解釋一下吧!
struct sockaddr {
unsigned short sa_family; /* 地族,當然也是 AF_xxx */
char sa_data[14]; /* 14 bytes 協議地址 */
};
啊,和我們的sockaddr_in差不多嘛,我沒騙你吧,只是把sa_data[14]分得更小更多我們
把sockaddr_in里除了sa_family外其他的加起來,也剛好是14
bytes耶!如果有興趣,
你也可以用sockaddr代替sockaddr_in,當然在實際編程中恐怕。。。很少或幾乎是沒
有人會這樣做的吧!
好了,讓我們回到connect吧,還有最后一個參數,說明要連接對向的大小,我們這
里是server大小~!
當然,如果連接出錯我們就exit(-1);閃人嘍~!
if(recv(socketf,buf,BUFSIZE,0)<0)
{
prinft("%s","recever error");
exit(-1);
}
else
printf("%s",buf);
recv(),接收數據,我這里就不發送了,從socketf接受BUFSIZE個字節的數據到buf里去;
close(socketf);
文件用完要關閉,套接口也是一樣,要close(socketf);
}
最后不要忘了關門
總結
以上是生活随笔為你收集整理的网络编程-socket的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: echarts3 地图只显示南沙群岛,刷
- 下一篇: jsp日期格式化显示