Linux系統程式設計(34)—— socket程式設計之TCP伺服器與客戶端的互動
前面幾篇中實現的client每次執行只能從命令列讀取一個字串發給伺服器,再從伺服器收回來,現在我們把它改成互動式的,不斷從終端接受使用者輸入並和server互動。
/* client.c */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include "wrap.h"
#define MAXLINE 80
#define SERV_PORT 8000
int main(int argc, char *argv[])
{
structsockaddr_in servaddr;
charbuf[MAXLINE];
intsockfd, n;
sockfd= Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family= AF_INET;
inet_pton(AF_INET,"127.0.0.1", &servaddr.sin_addr);
servaddr.sin_port= htons(SERV_PORT);
Connect(sockfd,(struct sockaddr *)&servaddr, sizeof(servaddr));
while(fgets(buf, MAXLINE, stdin) != NULL) {
Write(sockfd,buf, strlen(buf));
n= Read(sockfd, buf, MAXLINE);
if(n == 0)
printf("theother side has been closed.\n");
else
Write(STDOUT_FILENO,buf, n);
}
Close(sockfd);
return0;
}
編譯並執行server和client,看看是否達到了你預想的結果。
這時server仍在執行,但是client的執行結果並不正確。原因是什麼呢?仔細檢視server.c可以發現,server對每個請求只處理一次,應答後就關閉連線,client不能繼續使用這個連線傳送資料。但是client下次迴圈時又呼叫write發資料給server,write呼叫只負責把資料交給TCP傳送緩衝區就可以成功返回了,所以不會出錯,而server收到資料後應答一個RST段,client收到RST段後無法立刻通知應用層,只把這個狀態儲存在TCP協議層。client下次迴圈又呼叫write發資料給server,由於TCP協議層已經處於RST狀態了,因此不會將資料發出,而是發一個SIGPIPE訊號給應用層,SIGPIPE訊號的預設處理動作是終止程式,所以看到上面的現象。
為了避免client異常退出,上面的程式碼應該在判斷對方關閉了連線後break出迴圈,而不是繼續write。另外,有時候程式碼中需要連續多次呼叫write,可能還來不及呼叫read得知對方已關閉了連線就被SIGPIPE訊號終止掉了,這就需要在初始化時呼叫sigaction處理SIGPIPE訊號,如果SIGPIPE訊號沒有導致程式異常退出,write返回-1並且errno為EPIPE。
另外,我們需要修改server,使它可以多次處理同一客戶端的請求。
/* server.c */
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include "wrap.h"
#define MAXLINE 80
#define SERV_PORT 8000
int main(void)
{
structsockaddr_in servaddr, cliaddr;
socklen_tcliaddr_len;
intlistenfd, connfd;
charbuf[MAXLINE];
charstr[INET_ADDRSTRLEN];
inti, n;
listenfd= Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family= AF_INET;
servaddr.sin_addr.s_addr= htonl(INADDR_ANY);
servaddr.sin_port= htons(SERV_PORT);
Bind(listenfd,(struct sockaddr *)&servaddr, sizeof(servaddr));
Listen(listenfd,20);
printf("Acceptingconnections ...\n");
while(1) {
cliaddr_len= sizeof(cliaddr);
connfd= Accept(listenfd,
(structsockaddr *)&cliaddr, &cliaddr_len);
while(1) {
n= Read(connfd, buf, MAXLINE);
if(n == 0) {
printf("theother side has been closed.\n");
break;
}
printf("receivedfrom %s at PORT %d\n",
inet_ntop(AF_INET,&cliaddr.sin_addr, str, sizeof(str)),
ntohs(cliaddr.sin_port));
for(i = 0; i < n; i++)
buf[i]= toupper(buf[i]);
Write(connfd,buf, n);
}
Close(connfd);
}
}
經過上面的修改後,客戶端和伺服器可以進行多次互動了。
相關文章
- Linux系統程式設計(35)—— socket程式設計之TCP伺服器的併發處理Linux程式設計TCP伺服器
- Linux系統程式設計(33)—— socket程式設計之TCP程式的錯誤處理Linux程式設計TCP
- TCP程式設計之服務端和客戶端的開發TCP程式設計服務端客戶端
- Linux網路程式設計之socket簡單通訊--客戶端程式碼Linux程式設計客戶端
- Linux系統程式設計(37)—— socket程式設計之原始套接字Linux程式設計
- linux網路程式設計之用socket實現簡單客戶端和服務端的通訊(基於TCP)Linux程式設計客戶端服務端TCP
- linux下TCP socket程式設計初步(1)LinuxTCP程式設計
- Linux socket程式設計學習初步(3)--客戶端向伺服器請求檔案Linux程式設計客戶端伺服器
- 系統程式設計-網路-tcp客戶端伺服器程式設計模型(續)、連線斷開、獲取連線狀態場景程式設計TCP客戶端伺服器模型
- linux系統程式設計之程式(一):程式與程式Linux程式設計
- Linux Socket C語言網路程式設計:TCP SocketLinuxC語言程式設計TCP
- Linux網路程式設計之socket簡單通訊TCP--服務端程式碼Linux程式設計TCP服務端
- 客戶端Cookie中文程式設計 (轉)客戶端Cookie程式設計
- Windows Socket程式設計精華《TCP通訊伺服器》Windows程式設計TCP伺服器
- python網路-Socket之TCP程式設計(26)PythonTCP程式設計
- 001 Rust 網路程式設計,實現 TCP 服務端和客戶端程式Rust程式設計TCP服務端客戶端
- 【windows socket+TCP伺服器客戶端】WindowsTCP伺服器客戶端
- Windows網路程式設計附書程式碼(簡單的伺服器與客戶端)Windows程式設計伺服器客戶端
- Linux socket程式設計學習初步(4)--伺服器端多程式Linux程式設計伺服器
- linux Socket 程式設計Linux程式設計
- socket程式設計實現tcp伺服器_C/C++程式設計TCP伺服器C++
- socket程式設計在TCP中的應用程式設計TCP
- shell程式設計之免互動程式設計
- Linux系統程式設計之程式介紹Linux程式設計
- Java OAuth 2.0 客戶端程式設計(二): 客戶端憑據授權JavaOAuth客戶端程式設計
- 網路程式設計之socket程式設計
- Java Tcp協議socket程式設計學習JavaTCP協議程式設計
- C++客戶端程式(socket)C++客戶端
- SOCKET程式設計程式設計
- Linux系統程式設計——特殊程式之孤兒程式Linux程式設計
- Linux系統程式設計之匿名管道Linux程式設計
- 《Linux系統程式設計訓練營》8_Linux 終端與程式Linux程式設計
- linux下bluetooth程式設計(五)bluetooth與socketLinux程式設計
- Linux Socket 程式設計簡介Linux程式設計
- linux socket程式設計初步(2)Linux程式設計
- UNIX網路程式設計學習(18)--UDP回射(伺服器+客戶端)程式程式設計UDP伺服器客戶端
- (3)Tcp Socket程式設計的封裝類 TcpListener/TcpClientTCP程式設計封裝client
- 基於TCP協議的Socket網路程式設計( )TCP協議程式設計