點擊上方藍字可直接關注!方便下次閱讀。如果對你有幫助,麻煩點個在看或點個贊,感謝~
最近因爲新換了工作,文章沒有及時更新,還望大家見諒。
之前一直想做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研究的可能會少了,但是不會放棄的。
以後通信安全方面知識的學習會多一些,也會和大家做一些分享的。
學習和生活相似卻又不同,不過都需要不斷總結規律,讓其習以爲常成爲習慣!
學習就像:看山是山,看山不是山,看山還是山!
公衆號後臺留言可獲取整個文件。