socket网络编程(一)-----处理一个客户端请求的简单服务器

最近学习了socket网络编程。socket处于应用层和传输层之间,应用程序通过socket在不同主机、进程之间连接起来,交换处理数据,从而屏蔽了底层的传输协议细节,如TCP协议中的三次握手、四次挥手。通过socket,客户端可以连接到服务器端,向服务器发出请求,相应地,服务器向客户端返回请求结果。socket是Web开发的基础。

本章实现了一个简单的服务器\客户端模型:
服务器创建一个监听描述符,当有客户端连接请求时,返回一个本地连接描述符conn_sock,客户端发来的数据先缓存在这个描述符上,以供服务器读取。
客户端通过服务器IP地址,端口号发出连接请求,连接成功后返回一个本地的套接字client_sock。客户端向client_sock写入需要发送给服务器的数据,并且从此套接字读取服务器发来的结果。
处理请求本次主要时验证socket通信。服务器将客户端发来的英文字符进行大小写转换并返回给客户端。

下面是源代码:

服务器端:

#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ctype.h>
#include <strings.h>
#include <string.h>
#include <sys/stat.h>
#include <pthread.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <netdb.h> //gethostbyaddr
#define MAXLINE 1024
/*
  toggle是一个只能处理一个服务器请求的简单服务器
*/
void toggle(int conn_sock);
int startup(int *port);
void error_die(const char *sc);

int main(int argc, char **argv){
  int listen_sock, conn_sock, port, clientlen;
  struct sockaddr_in clientaddr;
  struct hostent *hp; //客户端名字信息,通过gethostbyaddr函数获取
  char *haddrp;       //客户端IP信息,在clientaddr中
  if(argc != 2){
    fprintf(stderr, "input:%s <port>\n", argv[0]);  
    exit(1);
  }
  port=atoi(argv[1]);  //string to int
  listen_sock = startup(&port);
  while(1){
    clientlen=sizeof(clientaddr);
    conn_sock=accept(listen_sock,(struct sockaddr*)&clientaddr,&clientlen);
    hp=gethostbyaddr((const char*)&clientaddr.sin_addr.s_addr,
       sizeof(clientaddr.sin_addr.s_addr),AF_INET);
    haddrp=inet_ntoa(clientaddr.sin_addr);
    printf("Server connected to %s(%s)\n",hp->h_name,haddrp);
    
    toggle(conn_sock);
    close(conn_sock);
  }
  exit(0);
}


void toggle(int conn_sock){
  int n;
  int i;
  char buf[MAXLINE];
  while(n=recv(conn_sock,buf,MAXLINE,0)){ 
    printf("toggle server received %d bytes\n",n);
    for(i=0;i<n;i++){
      if(isupper(buf[i]))
        buf[i]=tolower(buf[i]);
      else
        buf[i]=toupper(buf[i]);
    }
    send(conn_sock,buf,n,0);
  }
}

int startup(int *port)
{
 int httpd = 0;
 struct sockaddr_in name;

 httpd = socket(PF_INET, SOCK_STREAM, 0);
 if (httpd == -1)
  error_die("socket");
 memset(&name, 0, sizeof(name));
 name.sin_family = AF_INET;
 name.sin_port = htons(*port);
 name.sin_addr.s_addr = htonl(INADDR_ANY);//表示本地IP
 //绑定socket
 if (bind(httpd, (struct sockaddr *)&name, sizeof(name)) < 0)
  error_die("bind");
 //如果端口没有设置,提供个随机端口
 if (*port == 0)  
 {
  socklen_t  namelen = sizeof(name);
  if (getsockname(httpd, (struct sockaddr *)&name, &namelen) == -1)
   error_die("getsockname");
  *port = ntohs(name.sin_port);
 }
 //监听
 if (listen(httpd, 5) < 0)
  error_die("listen");
 return httpd;
}


void error_die(const char *sc)
{
 perror(sc);
 exit(1);
}

客户端:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#define MAXLINE 1024


//一个客户端程序
int open_client_sock(char *host,int port);
void error_die(const char *sc);

int main(int argc,char **argv){
  int client_sock,port,n;
  char *host,buf[MAXLINE];

  if(argc!=3){
    fprintf(stderr,"input:%s <host> <port>\n",argv[0]);
    exit(1);
  }
  host=argv[1];   //char *   server's name
  port=atoi(argv[2]);  //int    server's port

  client_sock=open_client_sock(host,port);

  while(fgets(buf,MAXLINE,stdin)!=NULL){
    n = send(client_sock,buf,strlen(buf),0);
    printf("send %d bytes\n",n);
    recv(client_sock,buf,MAXLINE,0);
    fputs(buf,stdout);
  }
  close(client_sock);
  exit(0);
}

//传入一个服务器主机名,监听端口,返回已连接描述符
int open_client_sock(char *host,int port){
  int http = 0;
  struct hostent *hp;
  struct sockaddr_in serveraddr;
  http = socket(AF_INET, SOCK_STREAM, 0);
  if(http == -1)
    error_die("socket");
 
  if((hp = gethostbyname(host)) == NULL)//由域名获取IP
    error_die("no host");
 
  memset(&serveraddr, 0, sizeof(serveraddr));
  serveraddr.sin_family = AF_INET;
  serveraddr.sin_port = htons(port);
  bcopy((char *)hp->h_addr_list[0], (char *)&serveraddr.sin_addr.s_addr, hp->h_length);
  if(connect(http, (struct sockaddr *)&serveraddr, sizeof(serveraddr))<0)
    error_die("can't connect");
  return http;
}

void error_die(const char *sc)
{
 perror(sc);
 exit(1);
}

测试结果:在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值