使用C语言编写基于TCP协议的Socket通讯程序实例分享

 更新时间:2016年03月22日 17:48:39   作者:hncdsun  
这篇文章主要介绍了使用C语言编写基于TCP协议的Socket通讯程序实例分享,能够实现包括重新连接与每分钟通信一次等的功能,需要的朋友可以参考下

tcp客户端示例

#include <errno.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <stdlib.h> 
#include <string.h> 
#include <netinet/in.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
 
typedef struct _NSS_HEADER 
{ 
  unsigned short     ProtocolVersion;    /* 协议版本信息 */ 
  unsigned short     MsgType;        /* 消息类型 */ 
  unsigned short     TransactionNo;     /* 传输编号 */ 
  unsigned short     PacketLength;      /* 数据包长度,包括Header */ 
}NSS_HEADER;  
 
int str_echo(int sockfd, unsigned short no) 
{ 
  ssize_t readLen; 
  ssize_t writeLen; 
  char  buf[8]; 
 
  NSS_HEADER *hdr = (NSS_HEADER*)buf; 
  memset( hdr, 0, sizeof(NSS_HEADER) ); 
  hdr->TransactionNo = no; 
 
  // 写数据 
  int nWriteLen = 0; 
  while ( true ) 
  { 
    writeLen = write(sockfd, &buf[nWriteLen], sizeof(NSS_HEADER)-nWriteLen); 
//    printf( "write %d/n", writeLen); 
    
    if (writeLen < 0 && errno == EINTR) 
    { 
      continue; 
    } 
    else if ( writeLen < 0 ) 
    { 
      perror ( "write:" ); 
      return -1; 
    } 
 
    nWriteLen += writeLen; 
    // 已写完,直接返回 
    if (nWriteLen >= sizeof(NSS_HEADER) ) 
    { 
      break; 
    } 
  } 
 
  printf( "send data successed. trans no: %d/n", no ); 
 
  // 读数据 
  int nReadLen = 8; 
  while ( true ) 
  {     
    readLen = read(sockfd, buf, nReadLen); 
//    printf( "read: %d/n", readLen ); 
    if (readLen < 0 && errno == EINTR) 
    { 
      continue; 
    } 
    else if ( readLen <= 0 ) 
    { 
      perror( "read:"); 
      return -1; 
    } 
    else  
    { 
      nReadLen -= readLen; 
      if (nReadLen <= 0 ) 
      { 
        break; 
      } 
    } 
  } 
 
  printf( "read response successed./n" ); 
 
  return 0; 
} 
 
int main(int argc, char **argv) 
{ 
  printf("client ip: %s/n", argv[1]); 
  printf("client port: %s/n", argv[2]); 
  printf("server ip: %s/n", argv[3]); 
  printf("server port: %s/n", argv[4]); 
 
  printf("/n service starting.../n/n"); 
  while( true ) 
  { 
    int   socketFd; 
    struct sockaddr_in svrAddr; 
    struct sockaddr_in localAddr; 
 
    socketFd = socket (AF_INET, SOCK_STREAM, 0); 
    if ( -1 == socketFd ) 
    { 
      perror( "socket:" ); 
      continue; 
    } 
 
    // 设置地址可复用 
    int option = 1; 
    setsockopt( socketFd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option) ); 
    // 客户端IP 
    memset(&localAddr, 0, sizeof(localAddr)); 
    localAddr.sin_family = AF_INET; 
    localAddr.sin_addr.s_addr = inet_addr( argv[1]); 
    localAddr.sin_port = htons (atoi(argv[2])); 
 
    int bindResult = bind(socketFd, (struct sockaddr *) &localAddr, sizeof(localAddr)); 
    if ( -1 == bindResult ) 
    { 
      perror( "bind:" ); 
      sleep(10); 
      close(socketFd); 
      continue; 
    } 
 
    // 服务器IP 
    memset(&svrAddr, 0, sizeof(svrAddr)); 
    svrAddr.sin_family = AF_INET; 
    svrAddr.sin_addr.s_addr = inet_addr( argv[3]); 
    svrAddr.sin_port = htons (atoi(argv[4])); 
 
    // 不断重连 
    int connResult = connect(socketFd, (struct sockaddr *) &svrAddr, sizeof(svrAddr)); 
    if ( -1 == connResult ) 
    { 
      perror( "connect:" ); 
      sleep(10); 
      close(socketFd); 
      continue; 
    } 
     
    printf (" connect %s:%s successed./n", argv[3], argv[4] ); 
 
    static unsigned short no = 0; 
    // 连接成功,每分钟发送一次数据 
    for ( ; ; ) 
    { 
      if ( -1 == str_echo(socketFd, no++) ) 
      { 
        break; 
      } 
       
      sleep( 60 ); 
    } 
    close(socketFd); 
  } 
} 

tcp服务器源码示例

#include <errno.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <stdlib.h> 
#include <string.h> 
#include <netinet/in.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
 
struct _NSS_HEADER 
{ 
  unsigned short     ProtocolVersion;    /* 协议版本信息 */ 
  unsigned short     MsgType;        /* 消息类型 */ 
  unsigned short     TransactionNo;     /* 传输编号 */ 
  unsigned short     PacketLength;      /* 数据包长度,包括Header */ 
}NSS_HEADER;  
 
void str_echo(int sockfd) 
{ 
  ssize_t readLen; 
  ssize_t writeLen; 
  char  buf[8]; 
 
  while ( true ) 
  { 
    readLen = read(sockfd, buf, 8); 
    if (readLen < 0 && errno == EINTR) 
    { 
      continue; 
    } 
    else if ( readLen <= 0 ) 
    { 
      perror( "read:"); 
      return ; 
    } 
    printf( "recv data successed. data len: %d/n", readLen ); 
 
    int nWriteLen = 0; 
    while ( true ) 
    { 
      writeLen == write(sockfd, &buf[nWriteLen], readLen-nWriteLen); 
 
      if (writeLen < 0 && errno == EINTR) 
      { 
        continue; 
      } 
      else if ( writeLen < 0 ) 
      { 
        perror ( "write:" ); 
        return; 
      } 
 
      nWriteLen += writeLen; 
 
      // 已写完,直接返回 
      if (nWriteLen >= readLen ) 
      { 
        break; 
      } 
    } 
 
    printf( "send data successed. data len: %d/n", readLen ); 
  } 
} 
 
int main(int argc, char **argv) 
{ 
  printf( "server ip: %s/n", argv[1] ); 
  printf( "server port: %s/n", argv[2] ); 
 
  printf( "/nservice starting ... /n/n" ); 
 
  int   listenfd, connfd; 
  pid_t  childpid; 
  socklen_t clilen; 
  struct sockaddr_in cliaddr, servaddr; 
 
  listenfd = socket (AF_INET, SOCK_STREAM, 0); 
  if ( -1 == listenfd ) 
  { 
    perror( "socket:" ); 
    exit(-1); 
  } 
 
  // 设置地址可复用 
  int option = 1; 
  setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option) ); 
 
  memset(&servaddr, 0, sizeof(servaddr)); 
  servaddr.sin_family = AF_INET; 
  servaddr.sin_addr.s_addr = inet_addr( argv[1]); 
  servaddr.sin_port = htons (atoi(argv[2])); 
 
  int bindResult = bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); 
  if ( -1 == bindResult ) 
  { 
    perror( "bind:" ); 
    exit(-1); 
  } 
 
  int listenResult = listen(listenfd, 5); 
  if ( -1 == listenResult ) 
  { 
    perror( "listen:" ); 
    exit(-1); 
  } 
 
  for ( ; ; )  
  { 
    clilen = sizeof(cliaddr); 
    connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen); 
    if ( -1 == connfd ) 
    { 
      perror( "accept:" ); 
      continue; 
    } 
 
    printf ("accept %s successed.fd: %d/n", inet_ntoa(cliaddr.sin_addr), connfd ); 
 
    if ( (childpid = fork()) == 0)  
    { /* child process */ 
      close(listenfd);  /* close listening socket */ 
 
      str_echo(connfd);  /* process the request */ 
 
      printf ("disconnect from %d ./n", connfd );  
 
      exit (0); 
    } 
  } 
  close(connfd);     /* parent closes connected socket */ 
} 

相关文章

  • C语言实现扫雷项目

    C语言实现扫雷项目

    这篇文章主要为大家详细介绍了C语言实现扫雷项目,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • 代码讲解C++继承和派生

    代码讲解C++继承和派生

    在本文中我们通过实例代码给大家讲解下C++继承和派生相关知识点,需要的朋友们学习下。
    2019-02-02
  • c语言conio.h基本知识点总结

    c语言conio.h基本知识点总结

    在本篇文章里小编给大家分享的是关于c语言conio.h是什么意思的相关知识点,需要的朋友们可以学习参考下。
    2020-02-02
  • C++基础入门教程(五):new和delete

    C++基础入门教程(五):new和delete

    这篇文章主要介绍了C++基础入门教程(五):new和delete,本文讲解了动态分配内存、new和delete的配对、new、delete与reatin、release的关系、动态数组等内容,需要的朋友可以参考下
    2014-11-11
  • C语言的Struct Hack笔记

    C语言的Struct Hack笔记

    这篇文章主要介绍了C语言的Struct Hack例子,个人的一篇笔记,需要的朋友可以参考下吧
    2014-04-04
  • 详解C语言中printf输出的相关函数

    详解C语言中printf输出的相关函数

    这篇文章主要介绍了C语言中printf输出的相关函数总结,是C语言入门学习中的基础知识,需要的朋友可以参考下
    2015-08-08
  • C语言实现简单万年历

    C语言实现简单万年历

    这篇文章主要为大家详细介绍了C语言实现简单万年历,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • C++ 类的赋值运算符''''=''''重载的方法实现

    C++ 类的赋值运算符''''=''''重载的方法实现

    这篇文章主要介绍了C++ 类的赋值运算符'='重载的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • 用C语言实现猜数字游戏

    用C语言实现猜数字游戏

    这篇文章主要为大家详细介绍了用C语言实现猜数字游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-10-10
  • 380行C++代码实现扫雷小游戏

    380行C++代码实现扫雷小游戏

    这篇文章主要为大家详细介绍了380行C++代码实现扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-01-01

最新评论