linux socket编程客户端模型(用getaddrinfo)

本文介绍了一个简单的TCP客户端程序实现,包括连接远程服务器、双向数据传输等功能。通过getaddrinfo获取地址信息,并利用select进行多路复用,实现了客户端与服务器之间的交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include "unistd.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "stdio.h"
#include "string.h"
#include 
#include 
#include 
#include 
void error(int status, int err,char *fmt, ...) {
        va_list ap;
 va_start(ap, fmt);
 vfprintf(stderr, fmt, ap);
        va_end(ap);
 if(err)
  fprintf(stderr,":%s(%d)/n",strerror(err),err);
        if(status)
    exit(status);
}
          
int  client_connect(const char *hostname,const char *service,struct sockaddr_in *server,const char *protocol,int flag){
  int sockfd,err;
  struct addrinfo hints,*res,*r;
  bzero(&hints,sizeof(struct addrinfo));
  hints.ai_family=AF_INET;
  
  if(strcmp(protocol,"udp")==0)
   hints.ai_socktype=SOCK_DGRAM;
  else if(strcmp(protocol,"tcp")==0)
   hints.ai_socktype=SOCK_STREAM;
  err=getaddrinfo(hostname,service,&hints,&res);
  
  if(err){
   printf("%s/n",gai_strerror(err));
 exit(0);
  }
  for( r = res; r; r = r->ai_next) {
   if((sockfd=socket(r->ai_family,r->ai_socktype,r->ai_protocol))<0)
  continue;
 if((r->ai_socktype==SOCK_DGRAM)&&(flag==0))
  break;
 if((((r->ai_socktype==SOCK_DGRAM)&&(flag==1))||(r->ai_socktype==SOCK_STREAM))&&(connect(sockfd,r->ai_addr,r->ai_addrlen)==0))
  break;
 close(sockfd);
  }
  
  if(r==NULL)
   error(1,0,"connect error!!/n");
 memcpy(server,(struct sockaddr_in *)r->ai_addr,r->ai_addrlen);
 freeaddrinfo(res);
 return sockfd;
  }

//tcpclient.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

void process_client(int s) {

     char buff[128];
     int rc,maxfd;
     fd_set rset;
     FD_ZERO(&rset);
     while(1) {
      FD_SET(s,&rset);
 FD_SET(0,&rset);
 maxfd=s+1;
 if(select(maxfd,&rset,NULL,NULL,NULL)==-1)
  error(1,0,"select error!");
 if(FD_ISSET(s,&rset)) {
       rc = recv(s,buff,sizeof(buff),0);
       if(rc <= 0)
          break;
  buff[rc]='/0';
  write(1,buff,rc);
 }
 if(FD_ISSET(0,&rset)) {
       if(fgets(buff,sizeof(buff),stdin)==NULL)
   shutdown(s,SHUT_WR);
       send(s,buff,strlen(buff),0);
 }
     }
     /*
     while(fgets(buff,sizeof(buff),stdin)!=NULL) {
      send(s,buff,strlen(buff),0);
      rc = recv(s,buff,sizeof(buff),0);
      if(rc <= 0)
         break;
 buff[rc]='/0';
 write(1,buff,rc);
 bzero(buff,sizeof(buff));
     }
     */
}

int main(int argc, char **argv) {
    struct sockaddr_in server,temp;
    char *hname, *sname;
    int s, c, len;
    if(argc < 2)
     error(1,0,"parameters less than 2/n");
    else if(argc == 2) {
     hname = NULL;
 sname = argv[1];
    }
    else if(argc == 3) {
     hname = argv[1];
 sname = argv[2];
    }
    s = client_connect(hname, sname, &server, "tcp",0);

    len=sizeof(temp);
    getsockname(s,(struct sockaddr *)&temp,&len);
    printf("local %s:%d/n",inet_ntoa(temp.sin_addr),ntohs(temp.sin_port));
    
    getpeername(s,(struct sockaddr *)&temp,&len);
    printf("remote %s:%d/n",inet_ntoa(temp.sin_addr),ntohs(temp.sin_port));
    process_client(s);
    close(s);
    exit(0);
}
 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值