linux網路程式設計--TCP/IP協議
阿新 • • 發佈:2019-02-08
特點
TCP協議的位於資料傳輸層,其上一層是應用層,因此其目的是為了實現一個應用於另一個應用之間資料傳輸。
TCP協議需要進行三次握手實現資料傳送和接收的同步。
第一次握手:客戶端向服務端提出連線請求。這時TCP SYN標 志置位。客戶端告訴服務端序列號區域合法,需要檢查。客戶端 在TCP報頭的序列號區中插入自己的ISN。服務端收到該TCP分 段後,。
第二次握手:接收主機通過發回具有以下專案的資料段表示回 復:同步標誌置位、即將傳送的資料段的起始位元組的順序號、應 答並帶有將收到的下一個資料段的位元組順序號
第三次握手:客戶端確認收到服務端的ISN(ACK標誌置位)。到此為止建立完整的TCP連線,開始全雙工模式的資料傳輸過程。
實現過程
1.客戶端程式
#include<stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> /* superset of previous */ #include <arpa/inet.h> #include <stdlib.h> #include <signal.h> #include <string.h> #define BUF_SIZE 512 /**********************所用到的函式******************************* int socket(int domain, int type, int protocol); 建立套接字函式 AF_INET IPV4協議 SOCK_STREAM 流套接字 int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen); 結構體sockaddr的成員 struct sockaddr { sa_family_t sa_family; char sa_data[14]; } struct sockaddr_in { sa_family_t sin_family; /* address family: AF_INET in_port_t sin_port; /* port in network byte order struct in_addr sin_addr; /* internet address }; struct in_addr { uint32_t s_addr; /* address in network byte order }; int listen(int sockfd, int backlog); sighandler_t signal(int signum, sighandler_t handler); int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen); char *fgets(char *s, int size, FILE *stream);//接收終端輸入檔案流 ********************************************************/ int main() { int client_id; struct sockaddr_in clientadd; char buffer[BUF_SIZE]; client_id=socket(AF_INET,SOCK_STREAM,0); //建立套接字 clientadd.sin_family=AF_INET; //結構體成員賦值 clientadd.sin_port=htons(9736);//指定埠號 clientadd.sin_addr.s_addr=inet_addr("192.168.1.121"); //繫結IP地址,此處的IP為伺服器IP if(connect(client_id,(struct sockaddr *)&clientadd,sizeof(clientadd))==-1)//建立連線 { //連結失敗 printf("connect failed!\n"); exit(EXIT_FAILURE); } printf("please input:"); fgets(buffer,BUF_SIZE,stdin); //向伺服器寫 write(client_id,buffer,BUF_SIZE);//將獲取的資料傳送至緩衝區 sleep(rand()%3); memset(buffer,0,strlen(buffer)); read(client_id,buffer,BUF_SIZE);//接收返回資料 printf("You input:%s\n",buffer); close(client_id); return 0; }
2.伺服器程式
伺服器程式主要實現從客戶端接收資料,將接收到的資料返回給客戶端。
#include<stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> /* superset of previous */ #include <arpa/inet.h> #include <stdlib.h> #include <signal.h> #include <string.h> #define BUF_SIZE 512 /********用到的函式************************ int socket(int domain, int type, int protocol); 建立套接字 AF_INET IPV4協議 SOCK_STREAM int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen); struct sockaddr { sa_family_t sa_family; char sa_data[14]; } struct sockaddr_in { sa_family_t sin_family; /* address family: AF_INET in_port_t sin_port; /* port in network byte order struct in_addr sin_addr; /* internet address }; struct in_addr { uint32_t s_addr; /* address in network byte order }; int listen(int sockfd, int backlog); sighandler_t signal(int signum, sighandler_t handler); int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); ********************************************************/ int main() { int socket_id,client_id; struct sockaddr_in serveradd; struct sockaddr_in clientadd; int clientlen; char buffer[BUF_SIZE+1]; socket_id=socket(AF_INET,SOCK_STREAM,0); //建立套接字 serveradd.sin_family=AF_INET; serveradd.sin_port=htons(9736);//指定埠好 serveradd.sin_addr.s_addr=htonl(INADDR_ANY); //繫結IP地址 這裡指定監聽的IP地址是任何一個訪問的IP if(bind(socket_id,(struct sockaddr *)&serveradd,sizeof(serveradd))==-1) { //繫結失敗 printf("connect failed!\n"); exit(EXIT_FAILURE); } //伺服器端需要繫結埠和IP,伺服器端需要對固定的埠和指定的IP進行監聽,因此需要進行bind操作,而客戶端部分不需要 listen(socket_id,5);//最大允許5個客戶端訪問 signal(SIGCHLD,SIG_IGN); while(1) { clientlen=sizeof(clientadd); printf("please waiting....\n"); client_id=accept(socket_id,(struct sockaddr *)&clientadd,&clientlen);//監聽zijincheng if(fork()==0)//新建一個子程序,在子程序中實現接收客戶端傳送過來的內容並將其傳送回去,同時顯示在終端上。 { read(client_id,buffer,BUF_SIZE); buffer[BUF_SIZE]='\0'; printf("You input :%s\n",buffer); sleep(rand()%3); write(client_id,buffer,BUF_SIZE); close(client_id); exit(EXIT_SUCCESS); } else { close(client_id);//關閉子程序 } } }