摘要:int err = bind(sockServer, (struct sockaddr *)&addr, sizeof(addr))。#include dir。

点击上方蓝字可直接关注!方便下次阅读。如果对你有帮助,麻烦点个在看或点个赞,感谢~

最近因为新换了工作,文章没有及时更新,还望大家见谅。

之前一直想做linux+qt方向的,然而现在变成嵌入式软件方向了。其实也还好吧,这样就需要对底层的一些东西了解,目前是智能交通行业了。还不知道美国这次对华为动手会对这些用芯片的行业造成多大影响 ......

再啰嗦几句,现在平均每天快10点到住的地方,所剩精力已经不咋多了;所以想对整个时间进行优化调整,一切都还在适应中 ~

程序平台与环境: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研究的可能会少了,但是不会放弃的。

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

学习和生活相似却又不同,不过都需要不断总结规律,让其习以为常成为习惯!

学习就像:看山是山,看山不是山,看山还是山!

公众号后台留言可获取整个文件。

相关文章