Linux 下tcp编程例子

2023-05-16

/* 服务器端server程序 */

/* 编译命令:gcc -Wall -g -o server server.c -lpthread */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <errno.h>
#include <signal.h>

#define PORT 8458
#define MAX_LISTEN 20
typedef struct MsgHead{
 unsigned char type;
 unsigned char BL[4];
}MH;

pthread_mutex_t mutex;
pthread_attr_t attr;

char *get_time_string(char *sbuf)
{
    time_t Now;
    struct tm *tm;
    struct tm temp_time;
 
    time (&Now);
 
    tm = localtime_r(&Now, &temp_time);
    sprintf(sbuf, "%.4d%.2d%.2d_%.2d%.2d%.2d",
            tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
            tm->tm_hour, tm->tm_min, tm->tm_sec);
 
    return sbuf;
}

char *GetFileName(char *filename)
{
 char strTime[20];
 char strFileName[64];
 
 memset(strTime,0x00,sizeof(strTime));
 memset(strFileName,0x00,sizeof(strFileName));

 sleep(1);

 get_time_string(strTime);

 strcpy(strFileName,"rec_");
 strcat(strFileName,strTime);
 strcat(strFileName,".dat");  
 
 strcpy(filename,strFileName);

 return filename;
}

int tcp_recv(int fd,int len, char *strRecv)
{
 char *p = strRecv;
 int iRet = -1,iRecvLen = -1,count = 0;
 fd_set rset;
 struct timeval tv;
 
 tv.tv_sec = 0;
 tv.tv_usec = 0;

 while(len > 0)
 {
  FD_ZERO(&rset);
  FD_SET(fd,&rset);
  
  iRet = select (fd+1,&rset,NULL,NULL,&tv);
  //printf("iRet = %d\n",iRet);
  if (iRet < 0)
  {
   printf("tcp select error:%s\n",strerror(errno));
   break;
  }
  else if (iRet == 0)
  {
   sleep(1);
   continue;
  }

  iRecvLen = recv(fd,p,len,0);
  
  if (iRecvLen > 0)
  { 
   len -= iRecvLen;
   p += iRecvLen;
   count += iRecvLen;
  } 
 }
 return count; 

void *recv_msg(void *clfd)
{
 MH *MsgHead = NULL;
 int iMHL,iBodyLen,iRet = -1,iType = -1,iRecCount = 0;
 char RecvBuf[1024] = {"\0"},sFileName[64] = {"\0"};
 int fd = *((int *)clfd);
 FILE *fp = NULL; 

 printf("clfd=%d\n",fd); 
 iMHL = sizeof(MH);

 /* 打开一个文件用于存放sql 语句 */
 pthread_mutex_lock(&mutex);
 GetFileName(sFileName);
 pthread_mutex_unlock(&mutex);
 
 printf("Filename:%s\n",sFileName);
 
 if ( 0 > strlen(sFileName))
 {
  printf("get filename failed\n");
  return NULL;
 }
    
 fp = fopen(sFileName,"w+");
 if (!fp)
 {
  printf("open file %s failed: %s\n",sFileName,strerror(errno));
  return NULL;
 } 

 fprintf(fp,"%s\n","set termout on");
 fprintf(fp,"%s\n","set feed off");
 
 while(1)
 {
  memset(RecvBuf,0X00,sizeof(RecvBuf));
  //Get message head
  iRet = tcp_recv(fd,iMHL,RecvBuf);
  if (iRet != iMHL)
  {
   printf("get msg head failed !\n");
   continue;
  }

  iBodyLen = 0;
  MsgHead = (MH *)RecvBuf;
  iType = (int)MsgHead->type;
  //printf("type :%d\n",iType);
  if (2 == iType)
  {
   printf("\nServer tell:client %d exit!\n\n",fd);
   //sleep(10);
   fprintf(fp,"%s\n","commit;");
   fclose(fp);
   close(fd);
   return 0;
  }

  iBodyLen += MsgHead->BL[0] * 256 * 256 * 256;
  iBodyLen += MsgHead->BL[1] * 256 * 256;
  iBodyLen += MsgHead->BL[2] * 256;
  iBodyLen += MsgHead->BL[3];
  //printf("BodyLen=%d\n",iBodyLen);
  
  memset(RecvBuf,0X00,sizeof(RecvBuf));
  iRet = tcp_recv(fd,iBodyLen,RecvBuf);
  if (iRet == iBodyLen)
  {
   RecvBuf[iBodyLen] = '\0';
   if (1000 > iRecCount)
   {
    fprintf(fp,"%s\n",RecvBuf);
    iRecCount++;
   }
   else
   {
    /* 本文件已写满1000 条记录 */
    fprintf(fp,"%s\n","commit;");
    fclose(fp);

    /* 重新打开一个文件写记录 */
    iRecCount = 0;
    memset(sFileName,0x00,sizeof(sFileName));
    
    pthread_mutex_lock(&mutex);
    GetFileName(sFileName);
    pthread_mutex_unlock(&mutex);
    printf("Filename:%s\n",sFileName);
 
    if ( 0 > strlen(sFileName))
    {
     printf("get filename failed\n");
     return NULL;
    }
    fp = fopen(sFileName,"w+");
    fprintf(fp,"%s\n","set termout on");
    fprintf(fp,"%s\n","set feed off");

    fprintf(fp,"%s\n",RecvBuf);
    iRecCount++;
   }
   
  }
 }
 return 0;
}

void sig_handler(int signo)
{
 switch (signo)
 {
  case SIGTERM:
  case SIGINT:
   printf("received SIGTERM or SIGINT(tid:%u)", (unsigned int)pthread_self());
   break;
  
  case SIGHUP:
   printf("received SIGHUP(tid:%u)", (unsigned int)pthread_self());
   break;
  
  case SIGUSR1:
   printf("received SIGUSR1(tid:%u)", (unsigned int)pthread_self());
   break;

 
  case SIGPIPE:
   printf("received SIGPIPE(tid:%u)", (unsigned int)pthread_self());
   break;
  
  default:
   printf("received signal %d(tid:%u)", signo, (unsigned int)pthread_self());
   break;
 }
}

int setup_sig_handlers(void)
{
 struct sigaction act;
 
 act.sa_handler = sig_handler;
 sigemptyset(&act.sa_mask);
 act.sa_flags = 0;
 sigaction(SIGTERM,&act,NULL);
 sigaction(SIGINT, &act, NULL);
 sigaction(SIGHUP, &act, NULL);
 sigaction(SIGUSR1,&act,NULL);
 sigaction(SIGUSR2,&act,NULL);
 sigaction(SIGPIPE, &act, NULL);

 return 0;
}

int main()
{
 struct sockaddr_in SerAddr,CliAddr;
 int serfd = -1,clfd = -1,iSize = -1,count = 0;
 int bufSize = 4 * 1024 * 1024;
 pthread_t tid[256];
 
 pthread_attr_init(&attr);
 pthread_mutex_init(&mutex,NULL);
 
 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
 
 setup_sig_handlers();
 
 iSize = sizeof(SerAddr);
 serfd = socket(PF_INET,SOCK_STREAM,0);
 if (0 > serfd)
 {
  printf("init socket failed:%d\n",serfd);
  return 0;
 }


 memset(&(SerAddr),0x00,sizeof(struct sockaddr_in));
 memset(&(CliAddr),0x00,sizeof(struct sockaddr_in));

 SerAddr.sin_family = AF_INET;
 SerAddr.sin_port = htons(PORT);
 SerAddr.sin_addr.s_addr = htonl(INADDR_ANY);

 if ( 0  > bind(serfd,(struct sockaddr *)&SerAddr,iSize))
 {
  printf("server bind  to port %d failed \n",PORT);
  return 0;
 }
 
 if ( 0 > setsockopt(serfd,SOL_SOCKET,SO_RCVBUF,&bufSize,sizeof(bufSize)))
 {
  printf("setsockopt error:%s",strerror(errno));
  return -1;
 } 

 if (0 > listen(serfd,MAX_LISTEN))
 {
  printf("listen failed\n");
  return 0;
 }
 
 while(1)
 {
  clfd = accept(serfd,(struct sockaddr *)&CliAddr,&iSize);
  if (0 > clfd)
  {
   printf("accept failed %s",strerror(errno));
   sleep(1);
   continue;
  }
  
  if (count < 256)
  { 
   pthread_create(&tid[count++],&attr,recv_msg,(void *)&clfd);
  }
  else
  {
   printf("\n\ntoo many threads \n\n");
   return - 1;
  }   
 }
 pthread_mutex_destroy(&mutex);
 pthread_attr_destroy(&attr);
 return 0;
}
 
/* 客户端 */

/* 编译命令  gcc -Wall -g -o client client.c */

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

typedef struct MsgHead{
 unsigned char type;
        unsigned char BL[4];
}MH;

int con_serv()
{
 struct sockaddr_in SerAddr;
 int tcpfd = -1,iPort = 8458,iCount = 0;
 char sIP[64] = {"\0"};
 int sndBufSize = 4 * 1024 * 1024;

 tcpfd = socket(AF_INET,SOCK_STREAM,0);
 
 if(tcpfd < 0)
 {
  printf("socket error:%s\n",strerror(errno));
  return -1;
 }
 
 if ( 0 > setsockopt(tcpfd, SOL_SOCKET, SO_SNDBUF, (char *)&sndBufSize, sizeof(sndBufSize)))
    {
            printf("make_tcp(): setsockopt failed for server address\n");
            return -1;
    } 
 
 memset(&(SerAddr),0x00,sizeof(SerAddr));
 memset(sIP,0x00,sizeof(sIP));
 strcpy(sIP,"127.0.0.1");

 SerAddr.sin_family = AF_INET;
 SerAddr.sin_port = htons(iPort);
 SerAddr.sin_addr.s_addr = inet_addr(sIP);

 for (iCount = 0; iCount < 3; iCount++)
 {
  if (0 > connect(tcpfd,(struct sockaddr *)&SerAddr,sizeof(struct sockaddr)))
  {
   printf("the %d times connect to machine: %s,port:%d failed \n",iCount + 1,sIP,iPort);
  }
  else
  {
   return tcpfd;
  } 
 } 
 return -1; 
 

void tcp_send(int tcpfd,int num)
{
 fd_set wset;
 struct timeval tv = {1,0};
 int i = 0,iRet = -1;
 char buf[128] = {"\0"},*p = NULL;
 char Msg[1024] = {"\0"};
 int iLen = 128;
 MH MsgHead,*MsHe = NULL;

 for (i = 0; i < num; i++)
 {
  memset(Msg,0x00,sizeof(Msg));
  memset(buf,0x00,sizeof(buf));
  p = Msg;
  //sleep(1);
  sprintf(buf,"string%d-string%d-string%d-string%d-string%d",i + 1,i + 1,i + 1,i + 1,i + 1);
  MsgHead.BL[0] = (unsigned char)(strlen(buf) / 256 /256 /256);
  MsgHead.BL[1] = (unsigned char)(strlen(buf) / 256 /256 );
  MsgHead.BL[2] = (unsigned char)(strlen(buf) / 256 );
  MsgHead.BL[3] = (unsigned char)(strlen(buf) % 256 );
  MsgHead.type = (unsigned char)0;

  memcpy(p,&MsgHead,sizeof(MH));
  p = p + sizeof(MH);

  memcpy(p,buf,strlen(buf));
  p = NULL;    
  iLen = sizeof(MH) + strlen(buf);
 
  while(iLen > 0)
  {
   FD_ZERO(&wset);
   FD_SET(tcpfd,&wset);
   iRet = select(tcpfd + 1,NULL,&wset,NULL,&tv);
   if ( 0 > iRet)
   {
    printf("select error%s  reconnect\n",strerror(errno));
    close(tcpfd);
    sleep(1);
    tcpfd = con_serv();
    continue ;
   }
   else if ( 0 == iRet)
   {
    continue;
   }
   else
   {
    iRet = send(tcpfd,Msg,iLen,0);
    if ( 0 > iRet )
    {
     printf("send failed\n");
    }
    else
    {
     iLen -= iRet; 
    } 
   }
  } 
 }

 printf("tcpfd:%d already send %d record,",tcpfd,num);
 
 printf("send diconnect request\n");
 MsHe = (MH *)Msg;
    memset(Msg,0x00,sizeof(Msg));
 MsHe->BL[0] = (unsigned char)0;
    MsHe->BL[1] = (unsigned char)0;
    MsHe->BL[2] = (unsigned char)0;
    MsHe->BL[3] = (unsigned char)0;
    MsHe->type = (unsigned char)2;
 iLen = sizeof(MH);
 iRet = send(tcpfd,Msg,iLen,0);
    if ( iRet != iLen)
    {
        printf("send failed\n");
    }
  
 return;
}

void *execute(void *num)
{
 int tcpfd = -1;
 int number = *((int *)num);
 
 printf("pthread_id = %u\n",(unsigned int)pthread_self());

 tcpfd = con_serv();

 if ( 0 < tcpfd )
 {
  tcp_send(tcpfd,number);
 }
 else
 {
  printf("connect to server failed!\n");
  return NULL; 
 } 
 //sleep(10);
 close(tcpfd);
 printf("\nclient exit!\n\n");
 return NULL;
}


int  main(int argc,char **argv)
{
 int num = 0,i = 0,sendrec = 0;
 pthread_t tid;
 
 if (argc == 1)
 {
  num = 5;
 }
 else
 {
  for (i = 0; i < strlen(argv[1]); i++)
  {
   if (!isdigit(argv[1][i]))
   {
    printf("please added a number string\n!");
    return 0;
   }
  }
  num = atoi(argv[1]);
  if (0 >= num || 65536 < num)
  {
   num = 5;
  }
  
 }
 printf("send %d record\n",num);
 
 sendrec = num;
 for (i = 0; i < 5; i++)
 {
  sendrec *= (i + 1);
  pthread_create(&tid,NULL,execute,(void *)&sendrec);
  sleep(1);
  sendrec = num;
 }
 for (i = 0; i < 5; i++)
 {
  pthread_join(tid,NULL);
 }
 return 0;  

 

转载于:https://blog.51cto.com/jeyochen/506453

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux 下tcp编程例子 的相关文章

  • tcpdump -w 和 -r 的使用

    tcpdump的说明文档是这样的 xff1a w 将原始的信息包写入 形式如 tcpdump w tmp result txt 我今天试了一下 xff0c 发现其写成的文件如果用cat vim来查看的话 xff0c 都显示为乱码 经过man
  • 如何用Go访问深层嵌套的JSON数据?

    原文来自https hashnode com post how 大多数情况下 xff0c 开发人员需要使用来自其他服务的JSON数据并对其进行查询 查询JSON文档非常耗时 在过去的几天里 xff0c 我正在为Golang编写一个包 xff
  • Identity Card

    Identity Card Time Limit 2000 1000 MS Java Others Memory Limit 32768 32768 K Java Others Total Submission s 995 Accepted
  • 华为S5700交换机开启WEB配置

    近来很多朋友问关于S5700开启WEB不成功的问题 xff0c 现整理出具体步骤和命令 提示 xff1a 华为交换机配置时 xff0c 输入命令前几个字母 xff0c 按TAB可以自动补全命令 xff0c 比如在系统视图下输入sh按下TAB
  • 托管堆上对象的大小(Size)和Layout

    前几天 xff0c 我介绍了托管环境下struct实例的Layout和Size xff0c 其中介绍了StructLayoutAttribute特性 xff0c 其实StructLayoutAttribute特性不只可以用在struct上
  • 网上十大黑客软件大曝光

    网上十大黑客软件大曝光 Internet网上的黑客网站多如牛毛 xff0c 黑客软件也越来越多 越来越黑 笔者现将这些黑客软件分门别类地曝一曝光 xff0c 并提出相应的解决方案 xff0c 以防患于未然 一 古老的WinNuke 平台 x
  • C# DataSet和DataTable详解[转]

    1 创建DataSet对象 xff1a DataSet ds 61 new DataSet 34 DataSetName 34 2 查看调用SqlDataAdapter Fill创建的结构 da Fill ds 34 Orders 34 D
  • 【Python】爬取网站图片

    import requests import bs4 import urllib request import urllib import os hdr 61 39 User Agent 39 39 Mozilla 5 0 X11 Linu
  • 纯C++实现的HTTP请求(POST/GET)

    纯C 43 43 实现的HTTP请求 xff08 POST GET xff09 xff0c 支持windows和linux xff0c 进行简单的封装 xff0c 方便调用 实现如下 xff1a include 34 HttpConnect
  • python subprocess执行shell命令

    2019独角兽企业重金招聘Python工程师标准 gt gt gt subprocess的目的就是启动一个新的进程并且与之通信 subprocess模块中只定义了一个类 Popen 可以使用Popen来创建进程 xff0c 并与进程进行复杂
  • HDTV片源

    微软的 点击进入 苹果 quicktime下载 点击进入 国内一个网站 不过收费 电击进入 还有思路 转载于 https blog 51cto com wangjian 1420
  • Onvif鉴权实现方式

    Onvif鉴权实现方式 Digest 61 B64ENCODE SHA1 B64DECODE Nonce 43 Date 43 Password gsoap中digest生成代码 xff1a int soap wsse add Userna
  • 一文搞定Java并发编程面试考点

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 1 在java中守护线程和本地线程区别 xff1f java中的线程分为两种 xff1a 守护线程 xff08 Daemon xff09 和用户线程 xff08 User
  • 数据结构c语言版创建链表实验报告,C语言数据结构-创建链表的四种方法

    结点类型 xff1a typedef int datatype typedef struct NODE datatype data struct NODE next Node LinkList 1 不带头结点的头插入法创建链表 每创建一个结
  • syslog-ng

    syslog ng配置 March 13th 2012 绚丽也尘埃 Leave a comment Go to comments syslog ng的配置非常简单直观 xff0c 于是乎配置好看看怎么用它实时收集日志 有两台服务器 xff0
  • CMAKE总结(1) .lib .dll .a .so libx.dll libx.dll.a

    2019独角兽企业重金招聘Python工程师标准 gt gt gt win 对应 linux lib a dll 注 so 注 xff1a win中若使用 dll需要一个附带的引入库 lib win gcc中若使用 dll需要一个附带的因入
  • curl命令详解

    cURL 1 手册页 名称 cURL transfer a URL 摘要 cURL 选项 URL 描述 cURL 是一个向服务器或从服务器传输数据的工具 xff0c 它支持HTTP HTTPS FTP FTPS SCP SFTP TFTP
  • curl命令常见用法汇总 good

    curl是一种命令行工具 xff0c 作用是发出网络请求 xff0c 然后得到和提取数据 xff0c 显示在 34 标准输出 34 xff08 stdout xff09 上面 curl是一个强大的命令行工具 xff0c 它可以通过网络将信息
  • Linux编程之select

    select系统调用的的用途是 xff1a 在一段指定的时间内 xff0c 监听用户感兴趣的文件描述符上可读 可写和异常等事件 select 机制的优势 为什么会出现select模型 xff1f 先看一下下面的这句代码 xff1a int
  • DIGEST认证

    为了弥补BASIC认证存在的弱点 xff0c 从HTTP 1 1起就有了DIGEST认证 DIGEST认证同样使用质询 响应的方式 xff08 challenge response xff09 但不会像BASIC认证那样直接发送明文密码 所

随机推荐