利用網路套接字實現TCP互動
阿新 • • 發佈:2019-01-24
我們來了解一下TCP互動流程:
大致流程如下:
(1)伺服器根據地址的型別(屬於ipv4還是ipv6等)、socket型別(比如TCP、UDP)去建立socket,創建出的套接字socket本質上是個檔案描述符。
(2)伺服器繫結IP地址和埠號到套接字socket
(3)伺服器socket**監聽**埠號請求,隨時準備接收客戶端發來的連線,但這個時候伺服器的socket並沒有被開啟。
(4)根據地址的型別(屬於ipv4還是ipv6等)、socket型別(比如TCP、UDP)去**建立socke**t,創建出的套接字socket本質上也是個檔案描述符。
(5)客戶端根據伺服器的ip地址和埠號
(6)伺服器socket**接收到客戶端的socket請求,被動開啟,開始接收客戶端的請求,並等待客戶端返回連線資訊。這個階段,伺服器的**accept方法是阻塞的,即等到剛才試圖連線的客戶端返回連線資訊,accept方法才能返回,才能繼續接收下一個最新的客戶端連線請求。
(7)客戶端連線成功,向伺服器傳送連線狀態資訊。
(8)伺服器accept方法返回,連線成功
(9)客戶端傳送訊息
(10)服務端接收訊息
(11)客戶端關閉
(12)服務端關閉
我們根據這個流程實現TCP互動:
tcpserver.c(伺服器)
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
//伺服器
int main(int argc, char* argv[])
{
if(argc!=3){
printf("Usage %s is port\n",argv[0]);
return 1;
}
//建立套接字
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0){
perror("socket");
return 2;
}
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(atoi(argv[2]));
local.sin_addr.s_addr = inet_addr(argv[1]);
//繫結
if(bind(sock, (struct sockaddr*)&local, sizeof(local))<0)
{
perror("bind");
return 3;
}
//監聽
if(listen(sock, 5)<0)
{
perror("listen");
return 4;
}
while(1)
{
char buf[1024];
buf[0]='\0';
struct sockaddr_in peer;
socklen_t len = sizeof(peer);
//接受請求
int new_sock=accept(sock, (struct sockaddr*)&peer,&len);
if(new_sock<0)
{
perror("accept");
return 5;
}
inet_ntop(AF_INET, &peer.sin_addr, buf, sizeof(buf));
printf("get a connect,ip:%s,port:%d\n",buf, ntohs(peer.sin_port));
while(1)
{
ssize_t s = read(new_sock, buf, sizeof(buf));
if(s > 0)
{
buf[s]='\0';
printf("[%s:%d] %s",inet_ntoa(peer.sin_addr),\
ntohs(peer.sin_port),buf);
}
else
{
printf("client quit\n");
break;
}
write(new_sock,buf,strlen(buf)+1);
}
}
close(sock);
return 0;
}
tcpclient.c(客戶端)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc,char *argv[])
{
if(argc != 3){
printf("Usage %s ip port\n",argv[0]);
return 1;
}
//建立套接字
int sock=socket(AF_INET,SOCK_STREAM, 0);
if(sock < 0)
{
perror("socket");
return 2;
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[2]));
server.sin_addr.s_addr = inet_addr(argv[1]);
//建立連線
int ret = connect(sock, (struct sockaddr*)&server, \
sizeof(server));
if(ret < 0){
perror("connect");
return 3;
}
printf("connect success...\n");
while(1){
char buf[1024];//緩衝區
buf[0]='\0';
printf("Please Enter:");
fflush(stdout);
ssize_t s = read(0, buf, sizeof(buf));
}
write(sock, buf, sizeof(buf));
if(strncmp(buf, "quit",4)==0)
break;
read(sock, buf, sizeof(buf));
printf("server :%s",buf);
}
close(sock);
return 0;
}
在本地網路中建立連線,執行結果如下: