专栏首页Pou光明Linux Tcp通信——服务器与客户端

Linux Tcp通信——服务器与客户端

之前一直想做linux+qt方向的,然而现在变成嵌入式软件方向了。其实也还好吧,这样就需要对底层的一些东西了解,目前是智能交通行业了。

程序平台与环境:ubuntu16.04 64位、 c语言、

Eclipse编辑器、makefile文件编译(非cmake进行编译)

一、Tcp Server 源程序

程序特点:

①只能接受一个客户端连接

②可实现客户端断开后循环监听客户端连接

③启用端口复用,即kill掉之后不会显示端口被占用

④打印客户端连接地址

思考:

①如何发送结构体数据?

②如何封装自己的c语言socket通信模块?

③不清空接收缓存会有什么效果呢?

1. 服务器程序源码:

#include <stdio.h>
#include <stdlib.h>

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


#define SERVERPORT 8000
#define MAXLIN 4096

int main(void)
{
  int sockServer = -1;
  int connfd = -1;
  struct sockaddr_in addrClient; //client addr

    //01 create socket
    sockServer = socket(AF_INET, SOCK_STREAM, 0);
    //check is success
    if (sockServer < 0)
    {
      printf("create socket server faild!\n");
        return -1;
    }
    else
    {
        printf("create socket server success!\n");
    }

    //02 init server, fullfill sockaddr_in
    struct sockaddr_in addr;
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(SERVERPORT);
    addr.sin_addr.s_addr = htonl(INADDR_ANY) ;// receive data from any ip

  //设置该端口可复用
  socklen_t buflen = 1;
  socklen_t len = sizeof(buflen);
  setsockopt(sockServer, SOL_SOCKET, SO_REUSEADDR, &buflen,len);

    //03 bind socket
    int err = bind(sockServer, (struct sockaddr *)&addr, sizeof(addr));

    if (err < 0)
    {
        printf("bind() called failed!\n");
        return -1;
    }
    else
    {
        printf("bind() called success! \n");
    }

    //04 set the socket to listen mode, ready to receive client requests
    if(listen(sockServer, 5) < 0)
    {
        printf("listen() called failed!\n");
        return -1;
    }
    else
    {
        printf("listen() called successful!\n");
    }

    socklen_t sin_size = sizeof(struct sockaddr_in);

    const int nTempLen = 4096;
    char *recvbuf = (char *)malloc((size_t)nTempLen);

    while(1)
    {
      printf("wait client connecting ......\n");
      connfd = accept(sockServer,
                        (struct sockaddr *)&(addrClient),
                        &sin_size);
printf(" client connect success !!! ip is: %s \n",(inet_ntoa)(addrClient.sin_addr));

        while(connfd)   //modify  TcpServerRecv
        {
            //取实际收到的数据长度
            int nRecv = recv(connfd, recvbuf, nTempLen, 0);
            printf("recv size is %d \n",nRecv);

            if(nRecv <=0 && errno != EINTR)
            {
                printf(" client disconnect !\n" );
                break;
            }

            if(nRecv > 1)
            {
              printf("%s \n",recvbuf);

                if(send(connfd,recvbuf,nTempLen,0)<0)
                {
                   printf("send msg error :%s(errno:%d)\n",strerror(errno),errno);
                }
            }

            memset(recvbuf, 0, strlen(recvbuf));

        }

    }

  puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
  return EXIT_SUCCESS;
}

2. Makefile文件模板

Makefile文件还没有深入研究

使用前进入到Makefile文件所在目录下,最好先 make clean,然后make

之前对cmake简单研究过,嵌入式开发用的还是更原始一些,用的make;还有就是写脚本指定的都是bash,现在指定的是sh~

APP_DIR = .

#include dir
INC_DIR = $(APP_DIR)/include
# libs dir
LIBS_DIR = $(APP_DIR)/libs

#LDFLAGS += -L$(LIBS_DIR) -

################################################################################
# Build config
################################################################################

# Comment/uncomment the following line to disable/enable debugging
DEBUG = n
ifeq ($(DEBUG),y)
  # "-O" is needed to expand inlines
  EXTRA_CFLAGS += -O -g -DDEBUG
else
  EXTRA_CFLAGS += -O2
endif

#APP_DIR = $(CURDIR)
APP_BIN = $(APP_DIR)/myserver
LDFLAGS += -lpthread

# test dir
#TEST_DIR = $(APP_DIR)/test/

LIBS += $(Libs) 
#EXTRA_CFLAGS +=-I INC_DIR 
EXTRA_CFLAGS += -I$(INC_DIR)
EXTRA_CFLAGS += -I$(MSGFRAME_DIR)

CFLAGS +=-Wall -MD

EXTRA_CFLAGS += -I. -lpthread
################################################################################
# Build Rules
################################################################################
#CC = $(CROSS_COMPILE)gcc

all: $(APP_BIN)

SRCS_Comm = myServer.c 
OBJS_Comm = $(SRCS_Comm:.c=.o)

$(APP_BIN) : $(OBJS_Comm) 
  $(CC) $(CFLAGS) $(OBJS_Comm) -o $@ $(LDFLAGS)

%.o: %.c 
  $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(INCLUDE) -c $< -o $@

clean: 
  @rm -rf $(APP_BIN) $(OBJS_Comm) $(APP_DIR)/*.d $(APP_DIR)/Unit/*.d

二、Tcp Client源程序

程序特点:

①通过读取标准输入获取发送字符串,点击回车进行发送

②对是否成功连接到server进行判断

注意:

未包含#include <sys/socket.h>该头文件会有下面的警告:

prevent implicit declaration of function ‘inet_addr’ [-Wimplicit-function-declaration]

#include <stdio.h>
#include <stdlib.h>

#include <sys/socket.h>
//prevent implicit declaration of function ‘inet_addr’ [-Wimplicit-function-declaration]
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>



#define PORT 8000
//#define SERV "192.168.23.1"
#define SERV "127.0.0.1"
#define BUFF 1024

int main(void)
{
  // 定义socket
  int sockfd = socket(AF_INET,SOCK_STREAM,0);
  // 定义sockaddr_in
  struct sockaddr_in skaddr;
  skaddr.sin_family = AF_INET;
  skaddr.sin_port   = htons(PORT);
  skaddr.sin_addr.s_addr = inet_addr(SERV);

  if( connect(sockfd,(struct sockaddr *)&skaddr, sizeof(skaddr)) < 0 )
  {
    printf("connect error \n");
    exit(1);
  }
  printf("connect server success !!! \n");

  char sendbuf[BUFF];

  while( fgets(sendbuf, sizeof(sendbuf), stdin) != NULL )
  {
    send(sockfd, sendbuf, strlen(sendbuf), 0);
    if( strcmp(sendbuf,"exit\n") == 0)
    {
      break;
    }
  }

  close(sockfd);

  puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
  return EXIT_SUCCESS;
}

三、程序效果

应该是公司电脑加密问题无法上传图片。

四、小结

以后Qt研究的可能会少了,但是不会放弃的。

以后通信安全方面知识的学习会多一些,也会和大家做一些分享的。

本文分享自微信公众号 - Pou光明(pou0230),作者:PouG

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-05-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • nodejs TCP服务器和客户端通信的socket结构

    nodejs服务器端调用net模块的createServer方法启动一个TCP服务器,这个方法要指定一个回调函数,每当新的客户端发起连接后,回调函数触发,客户端...

    Jerry Wang
  • Java利用TCP协议实现客户端与服务器通信【附通信源码】

    上一篇博客和大家分享了在网络编程中要注意的基础知识,关于IP、TCP、UDP以及端口和套接字的一些概念,想了解的小伙伴可以看我的这篇文章“盘点那些进行网络编程必...

    灰小猿
  • 客户端与服务器

    mwangblog
  • Java通过Socket实现TCP编程,实现用户登录之服务器相应客户端,客户端和服务端之间的通信

    用户1289394
  • TCP客户机-服务器

    1 僵尸进程 2 信号处理 信号: 1 由一进程发往另一进程 2 由内核发往某进程 僵尸状态: 父进程取回子进程的相关信息,进程的ID,终止状态,子进程的资源利...

    用户1154259
  • 基于 HTML5 WebGL 的 3D 服务器与客户端的通信

    HT_hightopo
  • TCP编程tcp服务器客户端服务端tcp服务端发送和接收消息客户端接受和发送消息tcp服务器使用多线程接受多个客户端服务端使用多进程接收多个客户端

    Socket是网络编程的一个抽象概念。通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协...

    Python攻城狮
  • 【Echo】实验 -- 实现 C/C++下TCP, 服务器/客户端 通讯

    书童小二
  • WebSocket 开发模拟客户端与有游戏服务器通信

    WebSocket 客户端测试功能   websocket是有标准的通信协议,在h2engine服务器引擎中继承了websocket通信协议,使用websock...

    知然
  • C#开发: 通信篇-TCP客户端

    张三的电脑(ip:192.168.1.110)上有一个网络应用程序A(通信端口5000),

    杨奉武
  • Android 开发: 通信篇-TCP客户端

    https://www.android-doc.com/reference/java/net/Socket.html

    杨奉武
  • ffrpc-c++进程间(服务器端、客户端)通信框架

    FFRPC github 地址 https://github.com/fanchy/FFRPC FFRPC 已经陆陆续续开发了1年,6月6日这天终于完成了我比较...

    知然
  • tcp文件下载客户端+服务端

    skylark
  • python创建tcp服务端和客户端

    py3study
  • Android之TCP服务器编程android 之TCP客户端编程

    推荐一个学java或C++的网站http://www.weixueyuan.net/,本来想自己学了总结出来再写博客,现在没时间,打字太慢!!!!,又想让这好东...

    杨奉武
  • TCP服务器端和客户端建立连接 - 客户端的回调处理

    Jerry Wang
  • TCP服务器端和客户端建立连接 - 服务器端的回调处理

    服务器端createServer的回调函数被执行时,说明来了一个新的客户端发起的连接:

    Jerry Wang
  • Go语言服务器开发之简易TCP客户端与服务端实现方法

    Go语言具备强大的服务器开发支持,这里示范了最基础的服务器开发:通过TCP协议实现客户端与服务器的通讯。 一 服务端,为每个客户端新开一个goroutine 代...

    李海彬
  • ESP8266_13服务器端模式下的TCP通信

    上一节说的是TCP客户端模式下的通信,这一节说一下服务器端模式下的通信,总体来说,代码是差不多的,只是关键地方有些调整。

    MCU起航

扫码关注云+社区

领取腾讯云代金券