[c++]socket的简单实现

论坛 期权论坛 脚本     
匿名技术用户   2021-1-2 11:32   54   0

socket使用的demo(并没有设置非阻塞)

server:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h> 

#include <netdb.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <stdio.h>                                                                                                                                                                                
#include <pthread.h>
#include <string>
using namespace std;

# define BUFFER_SIZE 1001


int deal_new_conn(int* p_connfd, struct sockaddr* p_req_addr,socklen_t* p_addr_len);

int main(int argc, char *argv[])
{
 // 生成socket的地址 (ip port等)
 char nAddr[20] = "127.0.0.1";  // 指定ip
 int nPort = 9012;    // port
 struct in_addr addr;
 if (inet_aton("127.0.0.1", &addr) < 0) //得到网络字节序的IP
 {
  printf("[ERROR] addr %s:%d is invalid\n", nAddr, nPort);
  return -1;
 }
 struct sockaddr_in serv_addr; 
 memset(&serv_addr, '0', sizeof(serv_addr)); //地址初始化清空
 serv_addr.sin_family = AF_INET;
 serv_addr.sin_addr.s_addr = addr.s_addr;
 serv_addr.sin_port = htons(nPort); 

 // 生成监听的socket_fd (file describe)
 int listenfd = 0, connfd = 0;
// listenfd = socket(AF_INET, SOCK_STREAM  | SOCK_NONBLOCK, 0); // 非阻塞  这里设置noblock后accept就为非阻塞函数,accpt不到就返回-1
 listenfd = socket(AF_INET, SOCK_STREAM , 0); //生成socket

 // 绑定fd socket
 if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
 {
  printf("[ERROR] bind error!");
  return -1;
 }

 // 开始监听 fd
 if(listen(listenfd, 10) == -1)  // 设置连接队列的长度 为 10
 {
  printf("[ERROR] listen return false;");
  return 0;
 }

 printf("start waiting connect.\n");
 while(1)
 {
  //收到请求
  struct sockaddr req_addr = { 0 };
  socklen_t in_addr_len = sizeof (req_addr);
  // 从监听的fd的队列中取一个接收到的connect, 返回这个connect的fd
  connfd = accept(listenfd, &req_addr, &in_addr_len); // 接受到一个connect 返回fd
  printf("\n\n=======\nnew client connected.\n");
  deal_new_conn(&connfd, &req_addr, &in_addr_len);
 }

}  // server.c 服务端


int deal_new_conn(int* p_connfd, struct sockaddr* p_req_addr,socklen_t* p_addr_len)
{
 printf("start deal_new_conn...\n");
 // 收到请求后返回数据的buffer
 char sendBuff[1025];
 memset(sendBuff, '0', sizeof(sendBuff)); 

 int connfd = *p_connfd;
 struct sockaddr req_addr = *p_req_addr;
 socklen_t addr_len = *p_addr_len;
 // 设置非阻塞
// int flags = fcntl(connfd, F_GETFL);
// fcntl( connfd, F_SETFL, flags|O_NONBLOCK);
 // 取请求来源的ipport
 char hbuf[100], sbuf[100];
 if (getnameinfo(&req_addr, addr_len, hbuf, sizeof(hbuf), sbuf,
    sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0)
      printf("host=%s, serv=%s\n", hbuf, sbuf);

 // 读请求内容多次读
 char recbuff[BUFFER_SIZE + 1];
 string rec;
 printf("===start read_data\n");
 for(;;)
 {
  int result_len = read(connfd,recbuff, BUFFER_SIZE);
//  if(result_len == -1 && (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN))
//  {
//   usleep(1);
//   printf("|%d", result_len);
//   continue;
//  }
  if(result_len > 0)
  {
   recbuff[result_len] = '\0';
   rec += recbuff;
   if(result_len != BUFFER_SIZE) 
   {
    printf("(break result_len != BUFFER_SIZE)\n");
    break;
   }
   printf("(continue)\n");
   continue;
  }
  printf("(break result_len <=0 )\n");
  break;
 }
 printf("[size:%d] ret:|%s|\n",rec.size(),  rec.c_str());
 printf("===end read_data\n");
 
 // 处理数据
 sleep(3); //阻塞三秒
 time_t ticks; 
 ticks = time(NULL);  // 返回当前时间
 snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", ctime(&ticks));  // 把结果输入到返回数据的buffer

 // 返回数据
 write(connfd, sendBuff, strlen(sendBuff));        // 写入返回数据
 close(connfd); //关闭当前连接
 printf("end deal_new_conn...\n");
 return 0;
}

server代码有点问题,如果read的内容刚好是buffer的整数倍时,会卡在最后一次read,,还没找到问题,,不过问题不大,socket常跟epoll共同使用,会设置为非阻塞, 循环读的方式会改变不会有这种问题。

client就比较简单了

#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  
#include<errno.h>  
#include<sys/types.h>  
#include<sys/socket.h>  
#include<netinet/in.h>  
#include<netdb.h>  
#include <sys/stat.h>
#include <fcntl.h>
#include<arpa/inet.h>
# include <unistd.h>
  
#define MAXLINE 4096  
  
  
int main(int argc, char** argv)  
{  
 int sockfd, n,rec_len;  
 char recvline[4096], sendline[4096]="qwertqwert1";  
 char buf[MAXLINE];  
 struct sockaddr_in servaddr;  
  
  
 if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ){  
  printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);  
  exit(0);  
  }  
  
  
 memset(&servaddr, 0, sizeof(servaddr));  
 servaddr.sin_family = AF_INET;  
 servaddr.sin_port = htons(9012);  
 if( inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr) <= 0 ){  
  printf("inet_pton error for 127.0.0.1\n");  
  exit(0);  
  }  
  
  
 if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0 ){  
  printf("connect error: %s(errno: %d)\n",strerror(errno),errno);  
  exit(0);  
  }  
  
  
 printf("send msg to server: \n");  
// fgets(sendline, 4096, stdin);  
 if( send(sockfd, sendline, strlen(sendline), 0) < 0 )  
 {  
  printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);  
  exit(0);  
  }  
 if((rec_len = recv(sockfd, buf, MAXLINE,0)) == -1) {  
     perror("recv error");  
     exit(1);  
  }  
 buf[rec_len]  = '\0';  
 printf("Received : %s ",buf);  
 close(sockfd);  
 exit(0);  
}  

参考链接:http://www.cnblogs.com/jiangzhaowei/p/8261174.html

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP