Unix Socket - 服務器端舉例

要使進程成為TCP服務器,您需要遵循下面給出的步驟

? ? ? ? - 使用socket()系統(tǒng)調(diào)用創(chuàng)建一個套接字。

? ? ? ? -?使用Bind()系統(tǒng)調(diào)用將套接字綁定到一個地址。對于Internet上的服務器套接字,地址由主機上的端口號組成。

? ? ? ? -?監(jiān)聽與Listen()系統(tǒng)調(diào)用的連接。

? ? ? ? -?使用read()和write()系統(tǒng)調(diào)用發(fā)送和接收數(shù)據(jù)。

現(xiàn)在讓我們將這些步驟以源代碼的形式呈現(xiàn)出來。將這段代碼放到server.c文件中,并用gcc編譯器編譯它。

#include <stdio.h>

#include <stdlib.h>

#include <netdb.h>

#include <netinet/in.h>

#include <string.h>

int main( int argc, char *argv[] ) {

? int sockfd, newsockfd, portno, clilen;

? char buffer[256];

? struct sockaddr_in serv_addr, cli_addr;

? int? n;


? /* First call to socket() function */

? sockfd = socket(AF_INET, SOCK_STREAM, 0);


? if (sockfd < 0) {

? ? ? perror("ERROR opening socket");

? ? ? exit(1);

? }


? /* Initialize socket structure */

? bzero((char *) &serv_addr, sizeof(serv_addr));

? portno = 5001;


? serv_addr.sin_family = AF_INET;

? serv_addr.sin_addr.s_addr = INADDR_ANY;

? serv_addr.sin_port = htons(portno);


? /* Now bind the host address using bind() call.*/

? if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {

? ? ? perror("ERROR on binding");

? ? ? exit(1);

? }


? /* Now start listening for the clients, here process will

? ? ? * go in sleep mode and will wait for the incoming connection

? */


? listen(sockfd,5);

? clilen = sizeof(cli_addr);


? /* Accept actual connection from the client */

? newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);

? if (newsockfd < 0) {

? ? ? perror("ERROR on accept");

? ? ? exit(1);

? }


? /* If connection is established then start communicating */

? bzero(buffer,256);

? n = read( newsockfd,buffer,255 );


? if (n < 0) {

? ? ? perror("ERROR reading from socket");

? ? ? exit(1);

? }


? printf("Here is the message: %s\n",buffer);


? /* Write a response to the client */

? n = write(newsockfd,"I got your message",18);


? if (n < 0) {

? ? ? perror("ERROR writing to socket");

? ? ? exit(1);

? }


? return 0;

}

處理多個連接

為了允許服務器同時處理多個連接,我們在上面的代碼中做了以下更改:

? ? ? ? -?將accept語句和下面的代碼放入一個無限循環(huán)中。

? ? ? ? - 連接建立后,調(diào)用fork()創(chuàng)建一個新進程。

? ? ? ? -?子進程將關(guān)閉sockfd并調(diào)用doprocessing函數(shù),將新的套接字文件描述符作為參數(shù)傳遞。當兩個進程完成它們的對話時,如doprocessing()返回所示,這個進程就會退出。

? ? ? ? -?父進程關(guān)閉newsockfd。由于所有這些代碼都處于無限循環(huán)中,它將返回到accept語句以等待下一個連接。

#include?<stdio.h>

#include?<stdlib.h>

#include?<unistd.h>

#include?<netdb.h>

#include?<netinet/in.h>

#include?<string.h>

void?doprocessing?(int?sock);

void?doprocessing?(int?sock)?{

???int?n;

???char?buffer[256];

???bzero(buffer,256);

???n?=?read(sock,buffer,255);


???if?(n?<?0)?{

??????perror("ERROR?reading?from?socket");

??????exit(1);

???}


???printf("Here?is?the?message:?%s\n",buffer);

???n?=?write(sock,"I?got?your?message",18);


???if?(n?<?0)?{

??????perror("ERROR?writing?to?socket");

??????exit(1);

???}


}

int?main(?int?argc,?char?*argv[]?)?{

???int?sockfd,?newsockfd,?portno,?clilen;

???char?buffer[256];

???struct?sockaddr_in?serv_addr,?cli_addr;

???int?n,?pid;


???/*?First?call?to?socket()?function?*/

???sockfd?=?socket(AF_INET,?SOCK_STREAM,?0);


???if?(sockfd?<?0)?{

??????perror("ERROR?opening?socket");

??????exit(1);

???}


???/*?Initialize?socket?structure?*/

???bzero((char?*)?&serv_addr,?sizeof(serv_addr));

???portno?=?5001;


???serv_addr.sin_family?=?AF_INET;

???serv_addr.sin_addr.s_addr?=?INADDR_ANY;

???serv_addr.sin_port?=?htons(portno);


???/*?Now?bind?the?host?address?using?bind()?call.*/

???if?(bind(sockfd,?(struct?sockaddr?*)?&serv_addr,?sizeof(serv_addr))?<?0)?{

??????perror("ERROR?on?binding");

??????exit(1);

???}


???/*?Now?start?listening?for?the?clients,?here

??????*?process?will?go?in?sleep?mode?and?will?wait

??????*?for?the?incoming?connection

???*/


???listen(sockfd,5);

???clilen?=?sizeof(cli_addr);


???while?(1)?{

??????newsockfd?=?accept(sockfd,?(struct?sockaddr?*)?&cli_addr,?&clilen);


??????if?(newsockfd?<?0)?{

?????????perror("ERROR?on?accept");

?????????exit(1);

??????}


??????/*?Create?child?process?*/

??????pid?=?fork();


??????if?(pid?<?0)?{

?????????perror("ERROR?on?fork");

?????????exit(1);

??????}


??????if?(pid?==?0)?{

?????????/*?This?is?the?client?process?*/

?????????close(sockfd);

?????????doprocessing(newsockfd);

?????????exit(0);

??????}

??????else?{

?????????close(newsockfd);

??????}


???}?/*?end?of?while?*/

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容