參照例程編寫的基於TCP的通信程序。
server段建立之後,鍵入客戶端運行命令和主機地址,能實現客戶端中輸入的信息打印到服務端。
客戶端:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define portnumber 3333
struct sockaddr_in serveraddr;
int sockfd;
char buffer[1024];
/**********************************************
hostent的定義如下:
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
#define h_addr h_addr_list[0]
}
h_name – 地址的正式名稱。
h_aliases – 空字節-地址的預備名稱的指針。
h_addrtype –地址類型; 通常是AF_INET。
h_length – 地址的比特長度。
h_addr_list – 零字節-主機網絡地址指針。網絡字節順序。
h_addr - h_addr_list中的第一地址。
**********************************************/
struct hostent *host;
int main(int argc,char *argv[])
{
if(argc!=2)
{
printf("abusent IP adress");
exit(1);
}
if((host=gethostbyname(argv[1]))==NULL)
{
fprintf(stderr,"gethostname errror\n");
}
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"socket cretate feault:&s\n",error(errno));
exit(1);
}
brezo(&serveraddr,sizeof(struct sockaddr_in)); //注意:要交關鍵字struct !
serveraddr.sin_family=AF_INET;
serveraddr.sin_port=htons(portnumber);
serveraddr.sin_addr=*((struct in_addr *)host->h_addr);
//serveraddr.sin_addr.s_addr=host->h_addr;
if(connect(sockfd,(struct sockaddr *)(&serveraddr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"Connect fealut:%s\n",error(errno));
exit(1);
}
printf("please input something:\n");
fgets(buffer, sizeof(buffer),stdin);
write(sockfd,buffer,strlen(buffer));
close(sockfd);
exit(0);
}
服務端:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define portnumber 3333
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int newfd;
int sockfd;
int addrsize;
char buffer[1024];
int main(int argc,char *argv[]) //此處不帶參數也可
{
int nbytes;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
// printf("scoket create error\n");
fprintf(stderr,"scoket create error:%s\n\a",strerror(errno));
exit(1);
}
bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(portnumber);
/*************************************************************************
int bind(int socket, const struct sockaddr *address,socklen_t address_len)
綁定IP,端口信息等到套接字。
socket:是一個套接字。
address:是一個sockaddr結構指針,該結構中包含了要結合的地址和端口號。
address_len:確定address緩衝區的長度
****************************************************************************/
if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"bind error:%s\n\a",strerror(errno));
//上一函數用於打印相應的錯誤信息 ,\a表示響鈴(電腦的聲音)
exit(1);
}
/*******************************************************************
使得一個進程可以接受其它進程的請求,從而成爲
一個服務器進程。在TCP服務器編程中listen函數把進程
變爲一個服務器,並指定相應的套接字變爲被動連接。
*********************************************************************/
if(listen(sockfd,5)==-1)
{
// printf("listen error\n");
fprintf(stderr,"listen error:%s\n\a",strerror(errno));
exit(1);
}
addrsize=sizeof(struct sockaddr_in);
while(1)
{
/**************************************************************
accept( SOCKET s, struct sockaddr FAR* addr,int FAR* addrlen);
s:套接口描述字,該套接口在listen()後監聽連接。
addr: 接收爲通訊層所知的連接實體的地址。
Addr參數的實際格式由套接口創建時所產生的地址族確定。
addrlen: 指向存有addr地址長度的整型數。
****************************************************************/
if((newfd=accept(sockfd,(struct sockaddr *)&(client_addr),&addrsize))==-1)
{
// printf("accept error\n");
fprintf(stderr,"accept error:%s\n\a",strerror(errno));
exit(1);
}
fprintf(stderr,"server get connection from %s\n",inet_ntoa(client_addr.sin_addr));
//inet_addr 和inet_ntoa用於在二進制地址格式與點分十進制字符串表示之間轉換
if((nbytes=read(newfd,buffer,1024))==-1)
{
// printf("read error\n");
fprintf(stderr,"read error:%s\n\a",strerror(errno));
exit(1);
}
/*****************************************************
與read對應的則是write(sockfd,buffer,strlen(buffer));
注意:server端讀的是new, client端寫的是sockfd
*****************************************************/
buffer[nbytes]='\0';
printf("server received:%s\n",buffer);
close(newfd);
}
//把while(1)去掉後客戶端結束時它也能結束
close(sockfd);
exit(0);
}