一 TCP協定socket程式設計流程圖
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICdzFWRoRXdvN1LclHdpZXYyd2LcBzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CX90EROVTSU1kejpWTmZEWjZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jM5IzNzAzM1EDOxEDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
二 程式設計執行個體
/*server.c*/
//tcp網絡協定程式設計
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#define PORT 4321
#define MAX_QUE_CONN_NM 5
#define BUFFER_SIZE 1024
int main()
{
int sockid; //套接字描述符
struct sockaddr_in server_sockaddr,client_sockaddr;
int i=1;
int sin_size;
char buf[BUFFER_SIZE];
int client_fd; //接收到的套接字ID
int recvbytes; //接收到的位元組數
//建立socket
/**********************
函數原型:int socket(int family,int type,int protocol)
函數參數:family 協定族
AF_INET IPv4協定
AF_INET6 IPv6協定
AF_LOCAL UNIX域協定
AF_ROUTE 路由套接字(socket)
type 套接字類型
SOCK_STREAM 位元組流套接字socket
protocol 0(原始套接字除外)
函數傳回值: 成功 非負套接字描述符
出錯 -1
**********************/
sockid=socket(AF_INET,SOCK_STREAM,0);
if(sockid == -1)
{
//建立套接字失敗
printf("socket error\n");
exit(1);
}
server_sockaddr.sin_family=AF_INET;
server_sockaddr.sin_port=htons(PORT); //端口号
server_sockaddr.sin_addr.s_addr=INADDR_ANY; //IP位址 //IP位址可以指定,或者使用宏INADDR_ANY
//表示運作套接字與伺服器的任一網絡接口進行綁定
bzero(&(server_sockaddr.sin_zero),8);
//允許重複使用本地位址與套接字進行綁定
/*******************************
函數原型:int setsockopt(int sockfd,
int level,
int optname,
const void *optval,
socklen_t optlen);
函數參數:sockfd 套接字的ID
level 選項定義的層次 支援SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6
optname 需設定的選項
optval 指針,指向存放選項待設定的新值的緩沖區
optlen optval緩沖區長度
********************************/
setsockopt(sockid,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i));
//綁定位址
/*********************
函數原型:int bind(int sockfd,struct sockaddr *my_addr,int addrlen)
函數參數:sockfd 套接字描述符
my_addr 本地位址
addrlen 位址長度
函數傳回值: 成功 0
出錯 -1
**********************/
if( bind(sockid,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr)) == -1 )
{
printf("bind error\n");
exit(1);
}
printf("bind success\n");
/*調用listen()函數,建立為處理請求的隊列*/
/**************
函數原型:int listen(int sockfd, int backlog)
函數參數:sockfd 套接字的ID
backlog 請求隊列中允許的最大請求數,一般設定為5
函數傳回值: 成功 0
出錯 -1
************/
if( listen(sockid,MAX_QUE_CONN_NM) == -1 )
{
printf("listen error\n");
exit(1);
}
printf("listen...\n");
sin_size=sizeof(client_sockaddr);
//等待連接配接
/***************
函數原型:int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen)
函數參數:sockfd 套接字描述符号
addr 用戶端位址
addrlen 位址長度
傳回值: 成功 接收到的非負套接字
出錯 -1
***************/
if( (client_fd=accept(sockid,(struct sockaddr*)&client_sockaddr,&sin_size)) == -1 )
{
printf("accept error\n");
exit(1);
}
printf("the client_id is:%d\n",client_fd);
memset(buf,0,sizeof(buf));
/*調用recv()函數,接收用戶端的請求*/
/***********************
函數原型:int recv(int sockfd,void *buf,int len,unsigned int flags);
函數參數: sockfd 套接字描述符号
buf 存放接收資料的緩沖區
len 資料長度
flags 一般為0
函數傳回值: 成功 實際接收到的位元組數
失敗 -1
***********************/
if( (recvbytes= recv(client_fd,buf,BUFFER_SIZE,0) ) == -1 )
{
printf("recv error\n");
exit(1);
}
printf("receive data %d\n",strlen(buf));
printf("receive a message:%s\n",buf);
//結束連接配接
close(sockid);
exit(0);
}
/*client.c*/
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <netdb.h>
#define PORT 4321
#define BUFFER_SIZE 1024
int main(int argc,char *argv[])
{
struct hostent *host;
int sockid; //套接字描述符
int sendbyts; //實際發送的位元組數
char buf[BUFFER_SIZE];
struct sockaddr_in serv_addr;
if(argc<3)
{
fprintf(stderr,"USAGE:./client Hostname(or ip address) Text\n");
exit(1);
}
/*位址解析函數*/
/***************************
函數原型:struct hostent *gethostbyname(const char *hostname);
函數參數:hostname 主機名
函數傳回值:成功 指向hostent的指針
失敗 -1
*****************************/
if( (host=gethostbyname(argv[1])) == NULL )
{
printf("gethostbyname error\n");
exit(1);
}
memset(buf,0,sizeof(buf));
sprintf(buf,"%s",argv[2]);
//建立socket
sockid=socket(AF_INET,SOCK_STREAM,0);
if(sockid == -1)
{
//建立套接字失敗
printf("socket error\n");
exit(1);
}
/*設定socket_in中的相關參數*/
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(PORT); //端口号
serv_addr.sin_addr=*((struct in_addr *)host->h_addr); //IP位址 //IP位址可以指定,或者使用宏INADDR_ANY
//表示運作套接字與伺服器的任一網絡接口進行綁定
bzero(&(serv_addr.sin_zero),8);
//連接配接伺服器
/*調用connect()函數主動發起對伺服器端的連接配接*/
/************************
函數原型: int connect(int sockfd, const struct sockaddr * addr, socklen_t *addrlen)
函數參數: sockfd 套接字描述符
addr 用戶端位址
addrlen 位址長度
函數傳回值: 成功 接收到的非負套接字
失敗 -1
***********************/
if( connect(sockid,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr)) == -1 )
{
printf("connect error\n");
exit(1);
}
/*發送消息給服務端*/
/*****************
函數原型:int send(int sockfd,const void *msg,int len,int flags)
函數參數:sockfd 套接字描述符
msg 指向要發送資料的指針
len 資料長度
flags 一般為0
函數傳回值:成功 實際發送的位元組數
失敗 -1
******************/
if( (sendbyts=send(sockid,buf,sizeof(buf),0)) == -1 )
{
printf("send error\n");
exit(1);
}
close(sockid);
return 0;
}
運作結果
三 參考書籍 《從實踐中學嵌入式linux應用程式開發》 華清遠見嵌入式學院