在Linux中使用C語言構建TCP網絡通信節點
我們都知道,TCP通信是面向對象,可靠的連接服務,故TCP通信節點在軟件設計中被廣泛應用,因此這裏實現構建一個簡單的TCP通信節點demo
- 軟件環境: deepin 5.11
1.服務端構建
1)socket() – 創建通信套接字
//1.創建套接字 --- socket()
/*
int socket(int domain, int type, int protocol);
參數: domain --- AF_INET 地址族
type --- 套接字類型
SOCK_STREAM(流式套接字)
protocol --- 0
*/
int sockfd = socket(AF_INET,SOCK_STREAM,0); //返回值0爲成功,-1爲失敗
if(sockfd == -1)
{
perror("socket"); //打印錯誤輸出
return -1;
}
printf("socket excute successful!\n");
2)bind() – 綁定套接字
//2綁定套接字 --- bind()
/*
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
參數: sockfd ——-- 套接字文件描述符
addr --- 通用地址結構
addrlen --- 地址的長度
*/
struct sockaddr_in myaddr; //IPV4地址結構體
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(8888); //自定義設置端口號 5001~65535
myaddr.sin_addr.s_addr = inet_addr("192.168.3.121"); //自定義設置爲此服務器所在的IP地址
if (bind(sockfd, (struct sockaddr*)&myaddr, sizeof(myaddr)) == -1) //0成功 -1失敗
{
perror("bind");
return -1;
}
printf("bind success!\n");
3)listen() – 設置監聽套接字
//3設置監聽套接字 --- listen()
/*
int listen(int sockfd, int backlog);
參數: sockfd --- 套接字文件描述符
backlog -- 監聽隊列的長度
*/
if(listen(sockfd,5) == -1)
{
perror("listen");
return -1; //返回現在執行的函數(結束函數)
}
printf("listen successful!\n");
4) accept() – 接受客戶端的連接
//4等待客戶端的連接 --- accept()
/*
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
參數: sockfd --- 套接字文件描述符
第二/三個參數設置爲NULL
*/
int connfd = accept(sockfd,NULL,NULL);
if(connfd == -1)
{
perror("accpet!");
return -1; //返回現在執行的函數(結束函
}
printf("accpet success!\n");
5) read() – 服務端收數據
//5收來自客戶端的數據 --- read()
/*
ssize_t read(int fd, void *buf, size_t count);
參數:fd --- 文件描述符
buf --- 緩衝區首地址
count --- 想要讀取的字節數
返回值:
成功: >0 --- 成功讀取的字節數
=0 --- 讀到文件末尾
失敗: -1 --- 設置errno
*/
char buf[1024];
while(1)
{
memset(buf,0,sizeof(buf)); //將 buf空間中的1024內容清空
read(connefd,buf,sizeof(buf)); //表示把buf中的呢熊讀入
int ret = read(connefd,buf,sizeof(buf));
if(ret == -1) //讀取失敗
{
perror("read!");
break;
}
else if(ret == 0) //寫端口關閉
{
printf("client close\n")
}
else //成功接收
{
printf("recv : %s\n");
}
if (0 == strcmp(buf, "exit")) //判斷是否退出
break;
//添加客戶端和服務端信息交互
printf("send: ");
fgets(buf,1024,stdin);
ret = write(connfd, buf, sizeof(buf));
if (ret == -1) {
perror("write");
break;
}
if (strcnmp(buf, "exit",4) == 0)
break;
}
6) close() – 關閉套接字
//6關閉套接字 --- close()
close(connfd); //關閉連接
close(sockfd); //關閉文件描述符
2.客戶端構建
客戶端的構建原理方式,步驟和服務端大似相同
1)socket() – 創建套接字
//1.創建套接字
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd == -1)
{
perror("socket");
return -1;
}
printf("socket excute successful!\n");
2)connect() – 主動連接服務器
原理步驟和綁定服務器設置相同
//2.連接服務器
struct sockaddr_in myaddr; //IPV4地址結構體
memset(&myaddr, 0, sizeof(myaddr));
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons(8888); //端口號 5001~65535
srvaddr.sin_addr.s_addr = inet_addr("192.168.3.121"); //設置IP地址
if (-1 == connect(sockfd, (struct sockaddr*)&myaddr, sizeof(myaddr))) {
perror("bind");
return -1;
}
printf("bind success!\n");
3)write() – 發數據
//3.發數據
char buf[1024];
int ret;
while(1) //循環從鍵盤輸入串
{
printf("send : ");
fget(buf,1024,stdin); //輸入字符串並存入buf
ret = write(sockfd,buf,sizeof(buf));
if(ret == -1)
{
perror("write");
break;
}
if (strncmp(buf, "exit",4) == 0)
break;
ret = read(sockfd, buf, sizeof(buf));
if (ret == -1) {
perror("read");
break;
}else if (0 == ret) {
printf("server close!\n");
break;
}
printf("recv: %s\n", buf);
if (strcnmp(buf,"exit",4 ) == 0)
break;
}
4)close() – 關閉套接字
//4.關閉
close(sockfd);
3.效果展示
4.全部代碼
- 服務端
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main()
{
//1創建套接字
//man socket查看手冊
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd == -1)
{
perror("socket");
return -1;
}
printf("socket excute successful!\n");
//2綁定套接字
struct sockaddr_in myaddr; //IPV4地址結構體
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(8888); //端口號 5001~65535
myaddr.sin_addr.s_addr = inet_addr("192.168.232.130"); //設置IP地址
if (-1 == bind(sockfd, (struct sockaddr*)&myaddr, sizeof(myaddr))) {
perror("bind");
return -1;
}
printf("bind success!\n");
//3設置監聽套接字
if(listen(sockfd,5) == -1)
{
perror("listen");
return -1; //返回現在執行的函數(結束函數)
}
printf("listen successful!\n");
//4接受客戶端的連接。並生成新的通信套接字
//accpet()
int connfd = accept(sockfd,NULL,NULL); //定義套接字
if(connfd == -1)
{
perror("accpet!");
return -1; //返回現在執行的函數(結束函
}
printf("accpet success!\n");
//5收數據
char buf[1024];
while(1)
{
memset(buf,0,sizeof(buf)); //將 buf空間中的1024內容清空
int ret = read(connfd,buf,sizeof(buf));
if(ret == -1) //讀取失敗
{
perror("read!");
break;
}
else if(ret == 0) //寫端口關閉
{
printf("client close\n");
}
else
{
printf("recv : %s\n");
}
if (0 == strncmp(buf, "exit",4)) //判斷是否退出
break;
//添加客戶端和服務端信息交互
printf("send: ");
fgets(buf,1024,stdin);
ret = write(connfd, buf, sizeof(buf));
if (ret == -1) {
perror("write");
break;
}
if (strcnmp(buf, "exit",4) == 0)
break;
}
//6關閉套接字
close(connfd);
close(sockfd);
return 0;
}
- 客戶端
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main()
{
//1.創建套接字
//socket();
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd == -1)
{
perror("socket");
return -1; //返回現在執行的函數(結束函數)
}
printf("socket excute successful!\n");
//2. 主動連接服務器
//connect();
struct sockaddr_in srvaddr; //IPV4地址結構體
memset(&srvaddr, 0, sizeof(srvaddr));
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons(8888); //端口號 5001~65535
srvaddr.sin_addr.s_addr = inet_addr("192.168.232.130"); //鏈接服務器的IP地址
if (-1 == connect(sockfd, (struct sockaddr*)&srvaddr, sizeof(srvaddr))) {
perror("bind");
return -1;
}
printf("bind success!\n");
//3.發數據
//write()
char buf[1024];
int ret;
while (1) {
printf("send: ");
fgets(buf,1024,stdin);
ret = write(sockfd, buf, sizeof(buf));
if (-1 == ret) {
perror("write");
break;
}
if (strncmp(buf, "exit",4) == 0) //判斷是否退出
break;
ret = read(sockfd, buf, sizeof(buf));
if (ret == -1) {
perror("read");
break;
}else if (0 == ret) {
printf("server close!\n");
break;
}
printf("recv: %s\n", buf);
if (strncmp(buf,"exit",4) == 0)
break;
}
//4.關閉套接字
close(sockfd);
return 0;
}