Linux單用戶CS模型TCP通訊完全註釋手冊 server 描述 實現一個簡單的Linux單用戶CS通訊,客戶端發送一串字元串,伺服器將其轉換為大寫後返回。 server 代碼 運行效果 客戶端輸入:hello,world 服務端轉換為大寫後返回,客戶端收到伺服器發回的數據後進行列印:HELLO, ...
Linux單用戶CS模型TCP通訊完全註釋手冊
server
描述
- 實現一個簡單的Linux單用戶CS通訊,客戶端發送一串字元串,伺服器將其轉換為大寫後返回。
server 代碼
```
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#define SERV_PORT 6666
int main(int argc,char *argv[])
{
int sfd, cfd;//定義伺服器的文件描述符std, 定義客戶端的文件描述符cfd, cfd用來與客戶端通訊,sfd用來接受客戶端接入請求.
int len, i;//定義讀取客戶端數據長度返回值len, 定義操作字元時的迴圈變數i
char buf[BUFSIZ], clie_IP[BUFSIZ];//定義buf接收字元串, 定義clie_IP接收套接字中客戶端IP
struct sockaddr_in serv_addr, clie_addr;//定義伺服器結構體,客戶端結構體
socklen_t clie_addr_len;//定義客戶端套接字長度
sfd = socket(AF_INET, SOCK_STREAM, 0);//創建一個伺服器套接字,返迴文件描述符
bzero(&serv_addr, sizeof(serv_addr));//給結構體清零
serv_addr.sin_family = AF_INET;//設置結構體協議族為IPv4
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//設置結構體IP為所有有效網卡的IP,這裡需要用htonl將INADDR_ANY轉為網路位元組序.
serv_addr.sin_port = htons(SERV_PORT);//設置埠,這裡htons為轉為網路位元組序
bind(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));//設置文件描述符與結構體綁定(ip, port, 網卡等).
listen(sfd, 2);//參數2為半連接及已連接但在等待accept分配文件描述符的連接數的總和,Linux預設最大128(該值可修改)
printf("Wait for client connect ...\n");
while(1)
{
clie_addr_len= sizeof(clie_addr);//初始化客戶端結構體長度
cfd = accept(sfd, (struct sockaddr *)&clie_addr, &clie_addr_len);//給客戶端連接分配文件描述符,並保存客戶端IP埠等信息到clie_addr結構體中
printf("cfd = ----------%d\n", cfd);
printf("client IP : %s, port : %d\n", /*列印客戶端IP,埠號,這裡從in_addr_t類型轉換到字元串類型,需要用inet_ntop函數*/
inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, clie_IP, sizeof(clie_IP)),
ntohs(clie_addr.sin_port)/*將埠號轉換為本地位元組序*/
);
do //迴圈處理客戶端請求
{
len = read(cfd, buf, sizeof(buf));
write(STDOUT_FILENO, buf, len);
for(i = 0; i< len; ++i)
{
buf[i] = toupper(buf[i]);
}
write(cfd, buf, len);
}while(len);
close(cfd);//通訊結束,關閉客戶端文件描述符
}
close(sfd);//通訊結束,關閉伺服器文件描述符
return 0;
}
```
client代碼實現
```
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define SERV_IP "127.0.0.1"
#define SERV_PORT 6666
int main(int argc,char *argv[])
{
int sfd, len;//定義與server通訊的文件描述符sfd, 定義讀取到的數據(server發的)的長度len
struct sockaddr_in serv_addr;//定義與server通訊的套接字serv_addr
char buf[BUFSIZ];//定義buf接收server發送的數據
sfd = socket(AF_INET, SOCK_STREAM, 0);//初始化文件描述符sfd,協議族為AF_INET(即IPv4), 應用協議為SOCK_STREAM(即TCP協議),第三個參數預設0
bzero(&serv_addr, sizeof(serv_addr));//將套接字清零
serv_addr.sin_family = AF_INET;//設置套接字協議族為IPv4
inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr);//將IP地址轉換為in_addr_t類型存入
serv_addr.sin_port = htons(SERV_PORT);//將埠轉為網路位元組序存入
connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));//按照套接字里伺服器信息連接伺服器,並設置sfd文件描述符用來通訊
while(1)//與伺服器通訊過程,本例為給server發送一行數據,然後列印server發回的數據.
{
fgets(buf, sizeof(buf), stdin);
int ret = write(sfd, buf, strlen(buf));
printf("write ret = %d\n", ret);
len = read(sfd, buf, sizeof(buf));
printf("read len = %d\n", len);
write(STDOUT_FILENO, buf, len);
}
close(sfd);//關閉文件描述符
return 0;
}
```
運行效果
- 客戶端輸入:hello,world
- 服務端轉換為大寫後返回,客戶端收到伺服器發回的數據後進行列印:HELLO,WORLD
如圖
存在問題
- 僅作學習建立TCP連接使用,不支持多用戶,未進行錯誤處理。