青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

什么是socket?socket就是...,我在這里就不抄書了,有興趣的同仁去查查書吧。
不過還要說一句,socket就是不同進程之間的一種通信方式。就象打電話是朋友之間的一種通信方式是一樣。個人理解:所謂“通信”,就是相互之間發(fā)送數(shù)據(jù)。有人理解socket是不同計算機之間的一種通信方
式,這是不確切的。兩個進程,不管是運行在同一臺計算機上,還是運行在不同計算機上,都可通過
socket技術(shù)進行通信。

socket套接字的使用需要有網(wǎng)卡的支持,所以socket一般都被用來在不同機器之間通信,而如果在同一臺計算機上的兩個進程進行通信,通常采用效率更高的共享內(nèi)存技術(shù)來實現(xiàn)。

兩個進程之間進行通訊,就需要兩個進程同時都在運行了(廢話),在具體實現(xiàn)中,兩個進程我們通常要區(qū)別對待,一個進程專門等待另一個進程給自己發(fā)消息,收到消息后進行處理,在把處理結(jié)果發(fā)送回去。我們把專門處理消息、提供服務(wù)的進程稱為服務(wù)器端,把發(fā)送消息、請求處理的進程稱為客戶端。總體過程就是客戶端發(fā)送一個消息給服務(wù)器端,服務(wù)器端進程收到消息進行處理,把處理結(jié)果發(fā)送給客戶端。恩,就是這樣。

還有一個問題,如果我現(xiàn)在有一個進程要跟另一臺計算機上的某個進程進行socket通信,那在我這個進程中如何指定另一個進程呢?這里還需要說一下另一個概念——端口,如果把操作系統(tǒng)比作一座房子的話,那端口就是房子的窗口,是系統(tǒng)外界同系統(tǒng)內(nèi)部進行通信的通道。在socket實現(xiàn)中,我們不進行另一個進程的指定,而是指定發(fā)送消息或接收消息的端口號。比如說現(xiàn)在進程A要給進程B發(fā)消息,我們會把消息發(fā)送到進程B所運行的計算機的端口N上,而進程B此時正在監(jiān)視端口N,這樣進程B就能收到進程A發(fā)送來的數(shù)據(jù),同樣進程B也把消息發(fā)送到該端口上,進程A也能從該端口收到進程B發(fā)送來的數(shù)據(jù),當然,這需要客戶端和服務(wù)器端關(guān)于端口號進行一個約定,即共同操作同一個端口。如果客戶端把消息發(fā)送到端口N1上,而服務(wù)器端監(jiān)視的是端口N2,那通信一定不能成功。端口號最大為65535,不能比這個再大了,但在我們自己的程序中盡量不要用小于1024的端口號,小于1024的端口好很多都被系統(tǒng)使用了,比如23被telnet所使用。

socket的實現(xiàn)是很簡單的,只要按照一定的步驟,就可馬上建立一個這樣的通信通道。

下面較詳細的介紹幾個核心的函數(shù):

SOCKET socket(int af, int type, int protocol);
無論是客戶端還是服務(wù)器端,下面這個函數(shù)是一定要用到的,也是最先用到的。
這個函數(shù)是要告訴系統(tǒng),給我準備好一個socket通道,我要和其它進程通信了。函數(shù)的返回值很重要,我們要記下來,它表示系統(tǒng)為我們準備好的這個socket通道,在以后的每個socket相關(guān)函數(shù)中都會用到,如果這個值等于SOCKET_ERROR,表示函數(shù)執(zhí)行失敗了。函數(shù)的參數(shù)我們分別給:PF_INET、SOCK_STREAM和IPPROTO_TCP。

int bind(SOCKET s, const sockaddr *addr, int namelen);
這個函數(shù)只有服務(wù)器端程序使用,作用是與某個socket通道綁定。可以用返回值判斷該函數(shù)執(zhí)行結(jié)果怎么樣,如果等于SOCKET_ERROR,那就是失敗了。第一個參數(shù)s,就是socket()函數(shù)的返回值;在結(jié)構(gòu)addr中,我們要給定一個端口號;namelen等于結(jié)構(gòu)sockaddr的大小。

int listen(SOCKET s, int backlog);
這個函數(shù)只有服務(wù)器端程序使用,作用是監(jiān)聽該端口。返回值與bind函數(shù)意義一樣。

int accept(SOCKET s, sockaddr *addr, int *addrlen);
這個函數(shù)只有服務(wù)器端程序使用,作用是響應客戶端的連接。返回值與bind函數(shù)意義一樣。

int connect(SOCKET s, const sockaddr *name, int namelen);
這個函數(shù)只有客戶端程序使用,作用是把客戶端和某個計算機的某個端口建立連接。返回值與bind函數(shù)意義一樣。第一個參數(shù)s,就是socket()函數(shù)的返回值;在結(jié)構(gòu)name中,我們要給定一個端口號和目的機器名;namelen等于結(jié)構(gòu)sockaddr的大小。

int send(SOCKET s, char *buf, int len, int flags);
int recv(SOCKET s, char *buf, int len, int flags);
這兩個函數(shù)就是發(fā)送數(shù)據(jù)和接收數(shù)據(jù),客戶端和服務(wù)器端程序都能用,哪個發(fā)送哪個接收不用說了吧?呵呵。
從函數(shù)的返回值可以檢查函數(shù)執(zhí)行是否成功。參數(shù)中buf是指向發(fā)送或接收的數(shù)據(jù)的指針,len是數(shù)據(jù)長度。flags我們給個0就可以(其實是我不知道具體含義)。

最后就是關(guān)閉socket了,這個很容易忘掉,但這個函數(shù)很重要,一定要用。
int closesocket(SOCKET s);


好了,關(guān)鍵函數(shù)就這么幾個,下圖是這幾個函數(shù)的執(zhí)行順序:

client端 service端

  |                    |
  v                 v
socket()       socket()
  |                          |
  |                          v
  |                        bind()
  |                          |
  |                          v
  |                        listen()
  |                          |
  |                          v
  |                        accept() 掛起,直到有客戶端來連接
  |                          |
  v                  三段握手過程   |
connect()       <-------------> |
  |                       |
  v   發(fā)送消息   v
  +---> send() ---------------> recv() <-------+
  |   |     . |
  |   |     . 處理消息 |
  |   v   響應消息   . |
  +---- recv() <--------------- send() --------+
  |     |
  v     |
close() ---------------> recv()
    |
    v
  closesocket()

上圖我覺得能很好的說明客戶端和服務(wù)器端的運行軌跡。

使用以上幾個函數(shù)在 linux 系統(tǒng)上就可成功建立一個socket通信連路,但如果在windows系統(tǒng)上,還要用到另一個函數(shù):
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
在windows系統(tǒng)上,首先要執(zhí)行這個函數(shù),所以要把這個函數(shù)放在socket()函數(shù)的前面。

我對上面的函數(shù)進行了一些封裝,為節(jié)省篇幅,我去掉所有注釋和非重要的函數(shù),在這里可以看到各個函數(shù)的具體用法:

在 VC60 環(huán)境下要運行下面的函數(shù),要包含頭文件 errno.h 和 winsock2.h,還有,在連接的時候要連接上ws2_32.dll文件。

這是頭文件內(nèi)容:
class Socket {
public:

bool setup();

void close();

bool connect(string host, int port);

bool listen();

int accept();

int recv(char *buf, int len);

int recv(int new_fd, char *buf, int len);

int send(const char *msg, int len);

int send(int new_fd, const char *msg, int len);

private:
  int _fd;
};

這是實現(xiàn)文件內(nèi)容:
bool Socket::setup() {

WSADATA wsd;
_fd = WSAStartup(MAKEWORD(2,2), &wsd);
if(_fd) {
return false;
}

_fd = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (_fd == -1) {
return false;
}
return true;
}

bool Socket::listen() {
struct sockaddr_in my_addr;

my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(52309);
my_addr.sin_addr.s_addr = INADDR_ANY;

if(::bind(_fd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == SOCKET_ERROR) {
return false;
}

if(::listen(_fd, BACKLOG) == SOCKET_ERROR) {
return false;
}

return true;
}

int Socket::accept()
{
int new_fd;
struct sockaddr_in their_addr;
int sin_size = sizeof(their_addr);

printf("accepting... \n");

new_fd = ::accept(_fd,
  (struct sockaddr *)&their_addr,
  &sin_size);
return new_fd == SOCKET_ERROR ? -1:new_fd;
}

bool Socket::connect(string host, int port) {
struct hostent *_h = gethostbyname(host.c_str());
if (_h == 0) {
return false;
}

struct in_addr *_addr = (struct in_addr *)_h->h_addr;
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr = *_addr;
sin.sin_port = htons(port);

if (::connect(_fd, (sockaddr *)&sin, sizeof(sin)) == SOCKET_ERROR) {
return false;
}

return true;
}

int Socket::recv(int new_fd, char *buf, int len)
{
int nb = ::recv(new_fd, buf, len, 0);
if (nb == -1) {
printf("Error! recv.\n");
}
return nb;
}

int Socket::recv(char *buf, int len) {
return recv(_fd, buf, len);
}

int Socket::send(const char *msg, int len) {
return send(_fd, msg, len);
}

int Socket::send(int new_fd, const char *msg, int len)
{
int nb = ::send(new_fd, msg, len, 0);
if (nb == -1) {
printf("Error! send.\n");
}

return nb;
}

void Socket::close() {

int trytimes = 0;
while(::closesocket(_fd) && trytimes < CLOSE_TRY_TIMES)
trytimes++;

if(trytimes == 10) {
printf("Cannot close socket!\n");
}
}

好,socket類是封裝好了,下面就是組織了,服務(wù)器端和客戶端是不一樣的,下面分別給出代碼,到這里已經(jīng)就很簡單了。

客戶端:
int main(int argc, char **argv)
{
printf("socket of client is run ...\n");
Socket s;
if (!s.connect("dezhi", 52309))
return 0;

char *msg = "ok, send a message.";
for (int i=0; i<10; i++) {
s.send(msg, 20);
printf("message = %s\n", msg);
}
s.send("q", 1);
s.close();

return 0;
}

服務(wù)器:
int main(int argc, char **argv) {
printf("socket of service is run ...\n");

Socket s;
s.listen();
int new_fd = s.accept();

char buf[8];
buf[7] = '\0';
while (1) {
if (s.recv(new_fd, buf, 5) != -1) {
  printf("%s\n", buf);
  if (buf[0] == 'q')
  break;
}
}
s.close();
}

下面為運行結(jié)果:
客戶端:
socket of client is run ...
Socket: WSAStartup success execute.
Socket: socket success execute.
Socket: Establish the connection to "127.0.0.1:52309"
message = ok, send a message.
message = ok, send a message.
message = ok, send a message.
message = ok, send a message.
message = ok, send a message.
message = ok, send a message.
message = ok, send a message.
message = ok, send a message.
message = ok, send a message.
message = ok, send a message.
Socket: Close connection to "127.0.0.1:52309"
Press any key to continue

服務(wù)器端
socket of service is run ...
Socket: WSAStartup success execute.
Socket: socket success execute.
bind ok!
listen ok!
accepting...
ok, send a message.
ok, send a message.
ok, send a message.
ok, send a message.
ok, send a message.
ok, send a message.
ok, send a message.
ok, send a message.
ok, send a message.
ok, send a message.
qk, send a message.
Press any key to continue

就到這里吧。socket的相關(guān)內(nèi)容可遠不止這些,我在這里只是給大家來個拋磚引玉,想深究?路還很漫長。關(guān)于詳細的實現(xiàn)代碼,去我的《源碼》上找吧,不放在這里,是為了讓篇幅小些。

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产欧美日韩不卡免费| 午夜久久影院| 久久九九免费| 久久亚洲一区二区| 久久精品夜色噜噜亚洲a∨| 久久久久久一区二区| 久久久精品tv| 欧美激情第8页| 亚洲精品国产无天堂网2021| 亚洲激情电影中文字幕| 一区二区三区视频在线看| 亚洲一区在线免费| 久久久久综合网| 欧美日在线观看| 精品9999| 亚洲图片你懂的| 久久成人精品一区二区三区| 欧美www视频在线观看| 日韩视频永久免费| 欧美在线观看网站| 欧美伦理91i| 伊人影院久久| 亚洲欧美色婷婷| 日韩一级黄色大片| 久久久久久一区| 午夜精品久久久久久99热软件| 欧美专区亚洲专区| 亚洲区一区二| 午夜影院日韩| 国产精品theporn88| 亚洲第一精品影视| 午夜在线视频观看日韩17c| 欧美aa国产视频| 欧美亚洲免费高清在线观看| 欧美日韩国产精品| 伊伊综合在线| 久久gogo国模裸体人体| 亚洲精品中文字幕女同| 久久久欧美精品| 国产精品在线看| 在线视频你懂得一区| 欧美成人免费在线视频| 欧美在线播放| 国产精品日韩精品| 亚洲先锋成人| 亚洲精品中文字幕有码专区| 噜噜噜躁狠狠躁狠狠精品视频| 国产精品色婷婷| 亚洲一级黄色| av成人免费在线| 欧美久久久久久久| 亚洲人成在线观看| 免费不卡中文字幕视频| 久久久777| 激情成人在线视频| 久久色在线观看| 久久精品一区二区三区四区 | 欧美一区二区精美| 国产精品v日韩精品v欧美精品网站| 91久久综合| 欧美高清不卡在线| 另类图片综合电影| 亚洲精品日韩激情在线电影| 亚洲国产91| 欧美精品一区二区三区在线看午夜 | 亚洲综合成人在线| 欧美午夜免费| 亚洲激情女人| 欧美高清hd18日本| 欧美高清一区| 99精品欧美一区二区蜜桃免费| 你懂的网址国产 欧美| 欧美成年人视频网站| 亚洲精品在线三区| 一本色道久久综合狠狠躁的推荐| 亚洲综合999| 亚洲在线视频免费观看| 国产精品手机在线| 久久精品123| 美女国内精品自产拍在线播放| 亚洲国产欧美精品| 日韩午夜三级在线| 国产一区深夜福利| 亚洲缚视频在线观看| 国产精品扒开腿做爽爽爽软件| 美女任你摸久久| 亚洲看片网站| 国产农村妇女毛片精品久久麻豆| 久久精品国产成人| 欧美a级理论片| 欧美亚洲一区二区在线| 久久九九99视频| 一区二区欧美日韩| 久久国产免费看| 洋洋av久久久久久久一区| 亚洲一区尤物| 91久久精品一区二区别| 亚洲欧美国产va在线影院| 在线播放日韩欧美| 中文久久精品| 亚洲日本激情| 久久国产一二区| 亚洲一区三区电影在线观看| 久久综合九色综合久99| 亚洲尤物在线| 欧美mv日韩mv国产网站| 久久久精品性| 欧美午夜电影一区| 亚洲国产成人午夜在线一区| 国产亚洲欧美一区二区| 亚洲青涩在线| 亚洲经典在线| 久久久久久久网| 久久99在线观看| 欧美午夜精品一区| 亚洲黄色免费电影| 在线日韩电影| 久久精品国产一区二区电影| 香蕉久久夜色精品国产| 欧美视频免费看| 亚洲精品国产视频| 亚洲精品免费在线| 欧美jjzz| 亚洲欧洲精品一区二区三区不卡| 在线日韩av| 久久天堂精品| 欧美xart系列高清| 伊人久久亚洲美女图片| 欧美一区二区免费| 欧美伊人久久| 国产日韩欧美| 欧美专区日韩专区| 久久久欧美一区二区| 国产亚洲欧美色| 久久精品国产清高在天天线| 久久久久综合| 亚洲春色另类小说| 久久综合色播五月| 亚洲福利视频免费观看| 亚洲精品欧美极品| 欧美理论在线| 欧美人成在线视频| 久久综合影视| 一区二区三区在线免费视频| 久久成人综合视频| 久久影院午夜片一区| 激情六月综合| 美女露胸一区二区三区| 亚洲国产黄色片| 亚洲婷婷综合久久一本伊一区| 国产精品啊v在线| 亚洲欧美综合v| 欧美成人r级一区二区三区| 亚洲欧洲日产国码二区| 欧美日韩1区2区| 午夜电影亚洲| 猫咪成人在线观看| 一本色道久久综合精品竹菊| 国产精品高潮视频| 欧美一区二区啪啪| 欧美激情1区2区| 亚洲欧美高清| 玉米视频成人免费看| 欧美大片免费观看在线观看网站推荐| 亚洲激情在线观看| 欧美一区二区三区免费观看视频| 黄色精品一区| 欧美日韩岛国| 久久久精品网| 一本色道久久88精品综合| 久久精品亚洲精品| 日韩视频免费在线观看| 国产欧美一区二区白浆黑人| 美日韩精品视频| 亚洲欧美中文日韩在线| 亚洲高清在线播放| 久久久久久久久久看片| 中文在线不卡| 亚洲国产婷婷香蕉久久久久久| 国产精品超碰97尤物18| 老司机一区二区三区| 亚洲一区二区三区在线播放| 欧美成人午夜| 欧美一区二区三区在线看| 1204国产成人精品视频| 国产精品伦一区| 欧美夫妇交换俱乐部在线观看| 午夜精品美女久久久久av福利| 欧美阿v一级看视频| 欧美一区二区大片| 在线视频精品一区| 亚洲国产乱码最新视频| 国产精品日日摸夜夜添夜夜av| 欧美激情第一页xxx| 欧美中日韩免费视频| 亚洲一二区在线| 一区二区精品在线| 日韩视频在线观看| 亚洲激情影视| 亚洲日韩欧美视频|