我們已經看過關於伺服器socket創建的教程,為了使進程TCP伺服器端需要執行以下步驟:
-
創建一個socket使用socket() 系統調用.
-
使用bind()系統調用套接字綁定到一個地址。對於互聯網上的伺服器套接字,地址包括主機的端口號。
-
使用listen()系統調用連接監聽。
-
accept() 系統調用形式接受連接。此調用通常會阻塞,直到有客戶端與伺服器連接。
-
發送和接收數據,使用read() 和 write() 系統調用。
現在要把上面這些步驟的形式寫成源代碼。把這個代碼寫server.c檔並用gcc編譯器編譯。
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.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語句和下麵的代碼在一個無限迴圈。
-
建立連接後,調用fork()創建一個新的進程。
-
子進程將關閉sockfd中致電doprocessing函數,通過新的套接字檔描述符作為參數。當兩個進程已經完成了他們對話中表示由doprocessing()返回,這個過程簡單地退出。
-
父進程關閉newsockfd。因為所有這些代碼是在一個無限迴圈,它接受語句將返回到等待下一個連接。
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.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);
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 */
}
|
Here is the simple implementation of doprocessing function.
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);
}
}
|
上一篇:
Socket輔助函數
下一篇:
Unix/Linux Socket 客戶端代碼實例
