⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpserver.c

📁 Linux网络编程教程适合初学者入门学习
💻 C
字号:
/* tcpServer.c */

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <netdb.h>

#include <stdio.h>

#include <unistd.h> /* close */

#define SUCCESS 0

#define ERROR   1

#define END_LINE 0x0A

#define SERVER_PORT 1500

#define MAX_MSG 100



/* 定义函数 readline */

int read_line();

int main (int argc, char *argv[]) {

  int sd, newSd, cliLen;

  struct sockaddr_in cliAddr, servAddr;		/* 套接字地址结构体 */

  char line[MAX_MSG];



  /* 建立套接字 */

  sd = socket(AF_INET, SOCK_STREAM, 0);

   if(sd<0) {

    perror("cannot open socket ");

    return ERROR;

  }

  

  /* 设定套接字地址结构体servAddr中的参数

 绑定服务器端口号 */



  servAddr.sin_family = AF_INET;

  servAddr.sin_addr.s_addr = htonl(INADDR_ANY);

  servAddr.sin_port = htons(SERVER_PORT);

  if(bind(sd, (struct sockaddr *) &servAddr, sizeof(servAddr))<0) {

    perror("cannot bind port ");

    return ERROR;

  }



  listen(sd,5);

  

/* 这里仍然是一个死循环,服务器端

等待客户端发来的连接请求		*/



  while(1) {

    printf("%s: waiting for data on port TCP %u\n",argv[0],SERVER_PORT);

    cliLen = sizeof(cliAddr);

    newSd = accept(sd, (struct sockaddr *) &cliAddr, &cliLen);

    if(newSd<0) {

      perror("cannot accept connection ");

      return ERROR;

    }



    /* 初始化line缓冲区,地址为0x0,长度为MAX_MSG */

    memset(line,0x0,MAX_MSG);

    

    /* 调用read_line函数来接收数据 */

    while(read_line(newSd,line)!=ERROR) {

      printf("%s: received from %s:TCP%d : %s\n", argv[0], 

	     inet_ntoa(cliAddr.sin_addr),

	     ntohs(cliAddr.sin_port), line);

    /* 初始化line缓冲区 */

      memset(line,0x0,MAX_MSG);

    } /* end of while(read_line) */

  } /* end of while (1) */

}



/* 下面这个程序仅仅是测试使用,在某种程度上说并不健全。*/

/*  当必要时数据从套接字缓冲区中读取,但不是按照字节顺序

一个字节一个字节的读取。所有被接收到的数据都被读取到缓

冲区中。可以设置END_CHAR作为数据行的结束符。read_line

函数调用成功则返回其读取的字节数,这些数据由指针line_to_return

指向。			*/

int read_line(int newSd, char *line_to_return) {

  static int rcv_ptr=0;

  static char rcv_msg[MAX_MSG];

  static int n;

  int offset;



  offset=0;

  while(1) {

    if(rcv_ptr==0) {

      /* 从套接字缓冲区中读取 */

      memset(rcv_msg,0x0,MAX_MSG); /* 初始化缓冲区 */

      n = recv(newSd, rcv_msg, MAX_MSG, 0); /* 等待、读取数据 */

      if (n<0) {

	perror(" cannot receive data ");

	return ERROR;

      } else if (n==0) {

	printf(" connection closed by client\n");

	close(newSd);

	return ERROR;

      }

    }

  

    /* 如果已经从套接字读取到了数据 */

    /* 或者 */

    /*缓冲区中还有其他数据 */



    /* 把指针line_to_return指向该缓冲区的数据 */

    while(*(rcv_msg+rcv_ptr)!=END_LINE && rcv_ptr<n) {

      memcpy(line_to_return+offset,rcv_msg+rcv_ptr,1);

      offset++;

      rcv_ptr++;

    }

    

    /* end of line + end of buffer => return line */

    if(rcv_ptr==n-1) { 

      /* 将最后一个字节设置为END_LINE */

      *(line_to_return+offset)=END_LINE;

      rcv_ptr=0;

      return ++offset;

    } 

    

    /* 尽管已经到了读取数据的末尾,

但是缓冲区中还有其他数据,

这时做如下处理: */

    if(rcv_ptr <n-1) {

      /* 设置最后一个字节为 END_LINE */

      *(line_to_return+offset)=END_LINE;

      rcv_ptr++;

      return ++offset;

    }



    /* 或者是已经到了缓冲区的末尾,但是缓冲区太小,装不下需要

接收的数据,这时等待套接字上新的数据到达  */

    if(rcv_ptr == n) {

      rcv_ptr = 0;

    } 

    

  } /*  end of while */

}/* end of main */

  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -