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

作者:hncdsun 时间:2023-07-05 03:30:03 

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语言,TCP,Socket
0
投稿

猜你喜欢

  • java递归算法的实例详解

    2021-06-07 12:15:17
  • Spring原生Rpc六种的正确打开方式实现示例

    2021-06-23 19:35:03
  • Java实现飞机航班管理系统的思路详解

    2022-08-20 19:48:42
  • Android点亮屏幕或屏幕解锁和锁定以及其他相关权限实现代码

    2021-12-21 16:44:26
  • SpringBoot中的yaml语法及静态资源访问问题

    2021-09-27 20:32:38
  • Java 程序员掌握 Spring Boot非常有必要

    2021-06-27 19:06:52
  • c# 编写的简单飞行棋游戏

    2022-12-05 05:10:59
  • C#中计算时间差中的小数问题解决

    2023-11-02 19:38:05
  • Java Spring MVC 上传下载文件配置及controller方法详解

    2023-11-22 04:13:59
  • SpringMVC使用ResponseEntity实现文件上传下载

    2023-08-20 02:10:58
  • android实现扑克卡片翻转

    2021-10-19 08:08:35
  • Java中的synchronized 优化方法之锁膨胀机制

    2023-10-02 03:44:15
  • MybatisX-Generator自动代码生成插件教程

    2022-01-08 10:50:48
  • Android实现EventBus登录界面与传值(粘性事件)

    2023-11-08 00:34:52
  • SpringBoot打War包上传到阿里云的LINUX服务器的操作方法

    2021-09-26 22:27:01
  • Java如何生成4位、6位随机数短信验证码(高效实现)

    2023-01-24 18:05:20
  • JAVA JDK8 List分组获取第一个元素的方法

    2021-06-24 13:07:51
  • intellij idea如何将web项目打成war包的实现

    2023-05-27 23:12:27
  • SpringBoot四种读取properties文件的方式(小结)

    2023-10-10 03:25:14
  • Android通知栏前台服务的实现

    2022-10-13 22:57:46
  • asp之家 软件编程 m.aspxhome.com