ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

头歌Linux系统编程

2021-05-20 19:32:19  阅读:1687  来源: 互联网

标签:return addr int 编程 头歌 Linux sockfd include struct


文章目录

嵌入式Linux应用开发入门

第1关 安装嵌入式开发工具

根据文档安装

第2关 交叉编译工具使用

C语言程序设计编辑与调试环境

第1关 打印输出 Hello World

#include<stdio.h>
	int main(void)
	{  
	/********* Begin *********/
        printf("Hello World");
	/********* End *********/
       return 0;
	}

第2关 打印输出图形

#include<stdio.h>
	int main(void)
	{  	
	/********* Begin *********/
        printf("    *\n");
        printf("   ***\n");
        printf("  OK\n");
        printf(" Hello!\n");
        printf("*********");
	/********* End *********/
       return 0;
	}

第3关 求3个数的最大值

#include<stdio.h>
	int main(void)
	{  
	/********* Begin *********/
        int a,b,c,max;
        scanf("%d,%d,%d",&a,&b,&c);
        if(b>a){
            max=b;
        }
        else{
            max=a;
        }
        if(max<c){
            max=c;
        }
         printf("max=%d",max);
	/********* End *********/
       return 0;
	}


第4关 熟悉C语言调试过程

#include"stdio.h"
int main(void)
  {
	  /********* Begin *********/
      int x;
      int y=2,z=3;
      scanf("%d",&x); 
      if(x==y+z)
          printf("*****");
      else  
          printf("#####");
      return 0;
	  /********* End *********/
  }

Linux之C编程入门

第1关 第一个C程序

vim test.c
#include <stdio.h>
void main(){
        printf("Hello world\n");
}
gcc test.c
./a.out      

第2关 Linux编译C程序

vim test.c
#include <stdio.h>
void main(){
        printf("Hello GCC\n");
}
gcc test.c -o firstExec
./firstExec          

第3关 Linux之静态库编写

vim Add.h
在Add.h中加入以下代码后保存用 :wq
#include <stdio.h>
int Add(int a,int b);

vim Add.c
在Add.c中加入以下代码后保存用 :wq
#include "stdio.h"
int Add(int a,int b){
        return a+b;
}

gcc -c Add.c -o Add.o
ar rcs libAdd.a Add.o

vim main.c
在main.c中加入以下代码后保存用 :wq
#include "Add.h"
int main(){
        int c=Add(10,2);
        return c;
}

gcc main.c -o exe -L ./ -lAdd
./exe


第4关 Linux之动态库编写

vim Sub.h
在Sub.h中加入以下代码后保存用 :wq
#include <stdio.h>
int Sub(int a,int b);

vim Sub.c
在Sub.c中加入以下代码后保存用 :wq
#include "stdio.h"
int Sub(int a,int b){
        return a-b;
}

gcc -fPIC -c Sub.c -o Sub.o
gcc -shared Sub.o -o libSub.so

vim main.c
在main.c中加入以下代码后保存用 :wq
#include <stdio.h>
#include "Sub.h"
int main(){
        int c=Sub(10,2);
        return c;
}

gcc main.c -o exe -L ./ -lSub
./exe

vim /etc/ld.so.conf
加入 /root 保存
ldconfig
./exe

Linux时间编程

第1关 Linux获取时间

#include <stdio.h>
#include <unistd.h>
#include <time.h>
typedef struct _localtimestruct
{
	int year;
	int month;
	int day;
	int hour;
	int minute;
	int second;
}localtimestruct;

time_t gettimesecond (void)
{
	/*************Begin***********/
	return time(NULL);
	/**************End************/
}
void getlocaltv (localtimestruct *ltinfo)
{
	/*************Begin***********/
	struct tm *current;
    time_t now_second;//=time(NULL);
    current=localtime(&now_second);
	ltinfo->year = current->tm_year;
	ltinfo->month = current->tm_mon;
    ltinfo->day = current->tm_mday;
    ltinfo->hour = current->tm_hour;
    ltinfo->minute = current->tm_min;
    ltinfo->second = current->tm_sec;	
	/**************End************/
}

第2关 Linux时间相互转换

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>

typedef struct _localtimestruct
{
	int year;
	int month;
	int day;
	int hour;
	int minute;
	int second;
}localtimestruct;
void func (void);
void timetrans (time_t current, char *time_str, localtimestruct *ltinfo, struct tm *tm_time)
{
	/*************Begin***********/
	strcpy(time_str,ctime(&current));
    memcpy(tm_time, gmtime(&current),sizeof(struct tm));
	ltinfo->year = tm_time->tm_year+1900;
    ltinfo->month = tm_time->tm_mon+1;
    ltinfo->day = tm_time->tm_mday;
    ltinfo->hour = tm_time->tm_hour;
    ltinfo->minute = tm_time->tm_min;
    ltinfo->second = tm_time->tm_sec;
	/**************End************/ 
}
long getdifftimeval (void)
{
	/*************Begin***********/
	struct timeval current,next;
    gettimeofday (&current, NULL);
	func();
	gettimeofday (&next, NULL);
	return (next.tv_sec-current.tv_sec)*1000*1000+next.tv_usec-current.tv_usec;
	/**************End************/
}

第3关 Linux 时间定时器

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>

void func (void);
static int count = 0;//the number of calling loopevent 

void loopevent (int signo)
{
	/************Begin************/
	if(signo==SIGPROF){

        func();
        count++;
    }
	if(count==5){
        struct itimerval it;
        it.it_interval.tv_sec = 0;
        it.it_interval.tv_usec = 0;
        it.it_value.tv_sec = 0;
        it.it_value.tv_usec = 0;
        setitimer(ITIMER_REAL, &it, NULL);
    }
	/*************End*************/
}
void setlocaltimer (void)
{
	/************Begin************/
	signal(SIGPROF , loopevent);
	struct timeval tv_interval = {1, 0};
    struct timeval tv_value = {3, 0};
    struct itimerval it;
    it.it_interval = tv_interval;
    it.it_value = tv_value;	
	setitimer(ITIMER_PROF , &it, NULL);
	/*************End*************/
}

Linux之文件操作

第1关 文件的创建

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main()
{
    /********** BEGIN **********/
    int ret=creat("testFile",S_IRUSR|S_IWUSR|S_IRGRP| S_IXGRP | S_IXOTH);
    if(ret==-1){
        printf("创建文件失败\n");
    }
    else{
        printf("创建文件失败\n");
    }
    /********** END **********/
    return 0;
}

第2关 文件打开与关闭

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

/************************
 * fileName: 需要被打开的文件路径
*************************/
int open_File(char *fileName)
{
	int fd = 0;   //存放文件描述符
	/********** BEGIN **********/
    fd=open(fileName,O_RDONLY);
	/********** END **********/

	return fd;
}

/************************
 * fd: 需要被关闭的文件描述符
*************************/
void close_File(int fd)
{
	/********** BEGIN **********/
	int ret = close(fd);
    if(ret==-1){
        printf("关闭文件失败\n");
    }
    else
    {
        printf("关闭文件成功\n");
    }
	/********** END **********/
}

第3关 文件读写操作

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

/************************
 * fd: 被打开文件的描述符
 * buf: 被写入字符串指针
*************************/
int write_File(int fd, char *buf)
{
	int writeSize = 0; //返回实际写入的字符个数

	/********** BEGIN **********/
    writeSize=write(fd,buf,strlen(buf));
   
	/********** END **********/

	return writeSize;
}

/************************
 * fd: 被打开文件的描述符
 * buf: 存放读取的字符串指针(假设buf足够大)
*************************/
int readLine(int fd, char *buf)
{
	int readSize = 0;  //返回实际读取的字符个数
	//提示:使用while循环每次只读取一个字符,判断该字符是否为换行符或者是否已经读取到文件末尾(读取到文件末尾返回值为0)
	/********** BEGIN **********/
	
    int result=-1;
    if(fd!=-1){
        while((result=read(fd,&buf[readSize],1))==1){
            if(buf[readSize]=='\n'){
                buf[readSize]='\0';
                break;
            }
            readSize++;
        }
    }
    if(result==-1) return result;
    else 
	/********** END **********/
	return readSize;
}

第4关 文件的删除

#include <stdio.h>
int main()
{
	/********** BEGIN **********/
    int ret = unlink("testFile");
    if (ret == -1)
    {
        printf("删除文件失败\n");
    }
    else
    {
        printf("删除文件成功\n");
    }	
	/********** END **********/
	return 0;
}

Linux进程控制

第1关 进程等待

#include <stdio.h>
#include <stdlib.h>
#include <string.h>  
#include <unistd.h> 
#include<sys/types.h> 
#include<sys/wait.h>

int g_i4event;
int process_wait(void)
{
    /********Begin********/
    pid_t pid = fork();
    g_i4event=1;
    if(pid==0){
        sleep(3);  
    }
    else{
        sleep(1);
        g_i4event=2;
        wait(NULL);
        g_i4event=3;
    }
     return 0;
    /*********End*********/
}

int process_waitpid(void)
{
    /********Begin********/
    pid_t pid = fork();
    g_i4event=1;
    if(pid==0){
        sleep(3);
    }
    else{
        sleep(1);
        g_i4event=2;
        waitpid(pid,NULL,0);
        g_i4event=3;
    }
    return 0;
    /*********End*********/
}

第2关 进程退出控制

#include <stdio.h>
#include <stdlib.h>
#include <string.h>  
#include <unistd.h> 
#include<sys/types.h> 
#include<sys/wait.h>
int g_i4event;
int father_son(void)
{
    /********Begin********/
	pid_t pid=fork();
    g_i4event=1;
    if(pid>0){
        sleep(1);
        g_i4event=2;      
    }
    else{
        sleep(2);
    }
    /*********End*********/
}
int son_father_nowait(void)
{
    /********Begin********/
	pid_t pid=fork();
	g_i4event=1;
    if(pid==0){
        sleep(1);
    }
    else{
        sleep(2);
        g_i4event=3;
    }
    /*********End*********/
}
int son_father_wait(void)
{
    /********Begin********/
	pid_t pid=fork();
	g_i4event=1;
    if(pid==0){
        sleep(1);  
    }
    else{
        wait(NULL);
        sleep(1);
        g_i4event=4;          
    }	
    /*********End*********/
}

第3关 system系统调用

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int g_i4event;
int do_system(void)
{
    /********Begin********/
	if(system("touch test.dat")!=-1)
    {
        g_i4event=1;
        return 0;
    }
    return -1;
    /*********End*********/
}

Linux高级进程通信

第1关 socket之本地通信

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

int localsocket_test(const char *buffer, char *recv_buff, int length)
{
	/*********begin***********/
    static struct sockaddr_un srv_addr;
    // creat unix socket
    int connect_fd = socket(PF_UNIX,SOCK_STREAM,0);
    if(connect_fd < 0)
    {
        perror("cannot creat socket");
        return -1;
    }
    srv_addr.sun_family = AF_UNIX;
    strncpy(srv_addr.sun_path, "./socket_test", strlen("./socket_test"));
    //connect server
    int ret = connect(connect_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));
    if (ret < 0)
    {
        perror("cannot connect server");
        close(connect_fd);
        return -1;
    }
    if(0 > write(connect_fd, buffer, strlen(buffer)))
    {
        perror("send message failed\n");
        close(connect_fd);
        return -1;
    }
    if(0 < read(connect_fd, recv_buff, length))
    {
        ret = 0;
    }
    else
    {
        ret = -1;
    }
    close(connect_fd);
    return ret;
	/**********end************/
}

第2关 命名管道

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <string.h>

void namepipe_commu(const char *buffer)
{
	/***********begin***********/
	int fd;
    int w_num;
	if((mkfifo("./my_fifo",0777)<0))
    {
        printf("cannot create fifo...\n");
        exit(1);
    }
    //以阻塞型只写方式打开fifo
    fd=open("./my_fifo",O_WRONLY);
    w_num=write(fd,buffer,strlen(buffer));
	/***********end***********/
}

第3关 消息队列

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

struct msgbuf
{
    long mytype;
    char bookname[100];
};

void mq_commu (void)
{
	/*********Begin*********/
	//创建消息队列
    int msgid = msgget((key_t)0x1234, 0666 | IPC_CREAT);

    struct msgbuf data[4];
    int i;
    for(i=0;i<4;i++){
        data[i].mytype=66;
    }

    strcpy(data[0].bookname, "C");
    strcpy(data[1].bookname, "Linux");
    strcpy(data[2].bookname, "Makefile");
    strcpy(data[3].bookname, "End");

    for(i=0;i<4;i++){
        msgsnd(msgid, &data[i], sizeof(struct msgbuf)-sizeof(long), 0);
        if(strcmp(data[i].bookname,"End")==0){
            break;
        }
        sleep(1);
    }	
	/**********End**********/
}

Linux之线程管理

第1关 创建线程

#include <stdio.h>
#include <pthread.h>

/************************
 * 参数start_routine: 函数指针,用于指向线程函数
 * 参数arg: 是线程函数的参数
 * 返回值: 返回线程ID
*************************/
pthread_t createThread(void *(*start_routine) (void *), void *arg)
{
	pthread_t thread;
	/********** BEGIN **********/
	 int ret = pthread_create(&thread, NULL, start_routine, arg);
	/********** END **********/
	return thread;
}

第2关 线程挂起

#include <stdio.h>
#include <pthread.h>

/************************
 * 参数thread: 需要等待结束的线程ID号
 * 返回值: 等待成功返回0,失败返回-1
 * 提示: 忽略线程返回值
*************************/
int waitThread(pthread_t thread)
{
	int ret = -1;
	/********** BEGIN **********/
    if(pthread_join(thread, NULL) == 0)
    {      
        return 0;
    }
    else
	/********** END **********/
	return ret;
}

第3关 线程终止

#include <stdio.h>
#include <pthread.h>

/************************
 * 参数thread: 需要等待结束的线程ID号
 * 返回值: 等待成功返回0,失败返回-1
 * 提示: 忽略线程返回值
*************************/
int cancelThread(pthread_t thread)
{
	int ret = -1;
	/********** BEGIN **********/
    if(pthread_cancel(thread)==0)return 0;
	else
	/********** END **********/
	return ret;
}

Linux之线程同步一

第1关 互斥锁

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

//全局互斥锁变量
extern pthread_mutex_t mutex;

//全局共享变量
extern char *buffer[3];
extern int position;

/************************
 * 参数arg: 是线程函数的参数
*************************/
void *ThreadHandler(void *arg)
{
	/********** BEGIN **********/
	 pthread_mutex_lock(&mutex);
	/********** END **********/
	
	buffer[position] = (char *)arg;
	sleep(1);
	position++;
	
	/********** BEGIN **********/
	pthread_mutex_unlock(&mutex);	
	/********** END **********/
	pthread_exit(NULL);
}

第2关 自旋锁

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

//全局自旋锁变量
extern pthread_spinlock_t lock;

//全局共享变量
extern char *buffer[3];
extern int position;

/************************
 * 参数arg: 是线程函数的参数
*************************/
void *ThreadHandler(void *arg)
{
	/********** BEGIN **********/
	pthread_spin_lock(&lock);
	/********** END **********/

	buffer[position] = (char *)arg;
	sleep(1);
	position++;

	/********** BEGIN **********/
	pthread_spin_unlock(&lock);
	/********** END **********/
	pthread_exit(NULL);
}

第3关 条件变量

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

//全局互斥锁变量和条件变量
extern pthread_mutex_t mutex;
extern pthread_cond_t cond;

//全局共享变量
extern char *buffer[3];
extern int position;
pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
/************************
 * 参数arg: 是线程函数的参数
*************************/
void *ThreadHandler1(void *arg)
{
	int i;
	for(i = 0; i < 3; i++)
	{
		usleep(500);
		position++;
		//通知ThreadHandler2函数执行赋值操作
		/********** BEGIN **********/
		pthread_cond_signal(&has_product);
		/********** END **********/
	}
	pthread_exit(NULL);
}

/************************
 * 参数arg: 是线程函数的参数
*************************/
void *ThreadHandler2(void *arg)
{
	/********** BEGIN **********/
	pthread_mutex_lock(&mutex);
    pthread_cond_wait(&has_product, &mutex);
	/********** END **********/

	buffer[position] = (char *)arg;
	
	/********** BEGIN **********/
	pthread_mutex_unlock(&mutex);
	/********** END **********/
	pthread_exit(NULL);
}

第4关 项目实战

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

struct Data
{
    int number;    //存放生产的数据
    struct Data *next;
};

//定义数据区头和尾
extern struct Data *beginData;    

const int max_number = 10;   //生产者与消费者的最大生产和消费任务
int consumer_number = 0;     //消费者已经消费的任务数
//全局互斥锁变量和条件变量
extern pthread_mutex_t mutex;
extern pthread_cond_t cond;

/************************
 * 参数arg: 是线程函数的参数
*************************/
void *Consumer(void *arg)
{
	while(1)
	{
		/********** BEGIN **********/
		pthread_mutex_lock(&mutex);
		while(beginData == NULL)
        {  
            pthread_cond_wait(&cond, &mutex);
        }
        if(beginData->number==-1){
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }      
        //消费数据
        printf("%d\n", beginData->number);
        consumer_number++;
        //将消费后的数据释放掉
        struct msg *tmp = beginData;
        beginData = beginData->next;
        free(tmp);
        pthread_mutex_unlock(&mutex);	
		/********** END **********/
	}
	pthread_exit(NULL);
}

Linux之网络编程(TCP)

第1关 TCP套接字创建与端口绑定

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

/************************
 * sockfd: 已经创建的套接字
 * port: 需要绑定的端口号
 * 返回值: 调用成功返回0,否则返回-1
*************************/
int bindSocket(int sockfd, unsigned short port)
{
	int ret = -1;
	/********** BEGIN **********/
    struct sockaddr_in addr;
    bzero(&addr, sizeof(addr));    //清空
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
	ret=bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
	if(ret){
        return 0;
    }
    else
	/********** END **********/
	return ret;
}

第2关 TCP监听与接收连接

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main()
{
	int sockfd;
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1)
	{
		printf("创建TCP套接字失败: %s\n", strerror(errno));
		return -1;
	}
	struct sockaddr_in addr;
	bzero(&addr, sizeof(addr));    //清空
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8888);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	//与8888端口进行绑定
	if(bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
	{
		printf("绑定端口失败: %s\n", strerror(errno));
		return -1;
	}

	//监听8888端口,并设置最大监听个数大于1
	/********** BEGIN **********/
	 if(listen(sockfd, 1) == -1)
    {
        printf("监听端口%d失败: %s\n", 8888, strerror(errno));
        return -1;
    }
    else
    {
        printf("监听%d端口中...\n", 8888);
    }
	
	/********** END **********/

	//接受来自客户端的第一个连接请求
	/********** BEGIN **********/
     int clientSockfd;
    struct sockaddr_in clientAddr;
    socklen_t clientAddrSize = sizeof(struct sockaddr_in);
	if((clientSockfd = accept(sockfd, (struct sockaddr *)&clientAddr, &clientAddrSize)) == -1)
    {
        printf("接受客户端请求失败: %s\n", strerror(errno));
        return -1;
    }
    else
    {
        printf("接受客户端请求成功\n");
        //inet_ntoa函数将网络地址转换成.点隔的字符串格式
        printf("客户端的IP地址:%s \t 端口:%d\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
    }	
	/********** END **********/
	close(sockfd);	
	return 0;
}

第3关 TCP连接的建立与终止

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define SERVER_IP "127.0.0.1"
/************************
 * ipAddr: 远程服务器的IP地址
 * port: 远程服务器的端口
*************************/
void connectSocket(char *ipAddr, unsigned short port)
{
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1)
	{
		printf("创建TCP套接字失败: %s\n", strerror(errno));
		return ;
	}	
	//连接到指定的服务器
	/********** BEGIN **********/
    struct sockaddr_in servAddr;
    bzero(&servAddr, sizeof(servAddr));    //清空
    servAddr.sin_family = AF_INET;
    servAddr.sin_port = htons(port);
    //使用inet_addr函数将点分十进制的IP转换成一个长整数型数
    servAddr.sin_addr.s_addr = inet_addr(ipAddr);
    //连接服务器
    if(connect(sockfd, (struct sockaddr *)&servAddr, sizeof(servAddr)) == -1)
    {
        printf("请求连接服务器失败: %s\n", strerror(errno));
        return -1;
    }
    else
    {
        printf("请求连接%s:%d成功\n", ipAddr, port);
    }	
	/********** END **********/

	close(sockfd);
}

第4关 TCP数据传送

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

#define PORT 8888

int main()
{
	int sockfd;
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1)
	{
		return -1;
	}
	struct sockaddr_in addr;
	bzero(&addr, sizeof(addr));    //清空
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	//与PORT端口进行绑定
	if(bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
	{
		return -1;
	}
	//监听PORT端口,并设置最大监听个数为5
	if(listen(sockfd, 5) == -1)
	{
		return -1;
	}
	int clientSockfd;
	struct sockaddr_in clientAddr;
	socklen_t clientAddrSize = sizeof(struct sockaddr_in);
	//接受连接请求
	if((clientSockfd = accept(sockfd, (struct sockaddr *)&clientAddr, &clientAddrSize)) == -1)
	{
		return -1;
	}
	else
	{
		char data[100];
		//接收客户端传来的数据,并打印出来(提示:换行打印)
		//同时将接收到的数据原样发送给客户端
		/********** BEGIN **********/
		memset(data,0,sizeof(data));
        while(recv(clientSockfd,data,sizeof(data),0)>0){
            printf("%s\n",data);
            send(clientSockfd,data,strlen(data),0);
           memset(data,0,sizeof(data));
        }
		/********** END **********/
	}
	close(clientSockfd);
	close(sockfd);
	
	return 0;
}

Linux之网络编程(UDP)

第1关 UDP套接字创建与端口绑定

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

/************************
 * port: 需要绑定的端口号
 * 返回值: 调用成功返回0,否则返回-1
*************************/
int UDPSocket(unsigned short port)
{
	int ret = -1;
	/********** BEGIN **********/
	int sockfd= socket(AF_INET, SOCK_DGRAM, 0);
    if(sockfd == -1)
    {
        printf("创建UDP套接字失败: %s\n", strerror(errno));
        return ret;
    }
    else
    {
        printf("创建UDP套接字成功\n");
         ret=0;
    }
    struct sockaddr_in addr;
	bzero(&addr, sizeof(addr));    //清空
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	//与port端口进行绑定
	if(bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
	{
        printf("绑定端口失败: %s\n", strerror(errno));
		return -1;
	}	
	/********** END **********/
	return ret;
}

第2关 UDP数据传送

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

#define PORT 8888

int main()
{
	int sockfd;
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd == -1)
	{
		return -1;
	}
	struct sockaddr_in addr;
	bzero(&addr, sizeof(addr));    //清空
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	//与PORT端口进行绑定
	if(bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
	{
		return -1;
	}
	char data[100];
	//接收客户端传来的数据,并打印出来(提示:换行打印)
	//同时将接收到的数据原样发送给客户端
	//当接收到"exit"字符串时,退出当前程序,不打印出"exit"字符串
	//提示:在每次接收字符串前要将存放字符串的变量清空
	/********** BEGIN **********/
	 struct sockaddr_in clientAddr;
    int clientAddrLen = sizeof(clientAddr);
    memset(data,0,sizeof(data));
    while(recvfrom(sockfd, data, sizeof(data), 0, (struct sockaddr *)&clientAddr, &clientAddrLen) > 0)
    {
        if(strcasecmp(data, "exit") == 0) break;
        sendto(sockfd, data, sizeof(data), 0, (struct sockaddr *)&clientAddr, sizeof(clientAddr));  //发送数据    
        printf("%s\n", data);
        memset(data,0,sizeof(data));
    }
	/********** END **********/
	close(sockfd);
	return 0;
}

第3关 项目实战

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

//定义数据块大小
char data[16];
//定义服务器端口和服务器地址
#define PORT 8889
#define SERVER_IP "127.0.0.1"

int main(int argc, char *argv[])
{
	int sockfd;
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd == -1)
	{
		return -1;
	}
	struct sockaddr_in servAddr;
	int servAddrLen = sizeof(servAddr);
	bzero(&servAddr, sizeof(servAddr));
	servAddr.sin_family = AF_INET;
	servAddr.sin_port = htons(PORT);
	servAddr.sin_addr.s_addr = inet_addr(SERVER_IP);
	
	//由用户传入的要下载文件的名称
	char *downLoadFileName = argv[1];
	printf("%s\n", argv[1]);
	//先在本地创建要下载的文件
	int fd = open(downLoadFileName, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
	//向服务器发送要上传文件的名称
	sendto(sockfd, downLoadFileName, strlen(downLoadFileName), 0, (struct sockaddr *)&servAddr, servAddrLen); 	
    /********** BEGIN **********/
   	struct sockaddr_in clientAddr;
    int clientAddrLen = sizeof(clientAddr);
    int recvLen;
	//接收来自客户端发来的数据
    while((recvLen = recvfrom(sockfd, data, sizeof(data), 0, (struct sockaddr *)&servAddr, &servAddrLen)) > 0)
    {
        //根据自定义的协议来判断客户端发送来的数据块类型
        if(data[0] == 'e')
        {
            //上传文件完成,关闭当前打开的文件
            close(fd);
            break;
        }
        else
        {
            //数据块为上传文件的内容,将内容写入到新创建的文件中
            //因为data的第一个字符为文件块类型,所以只需从第二个字符开始写文件
            write(fd, &(data[1]), recvLen - 1);
        }
        //给客户端回复一个接收确认的标识OK
        sendto(sockfd, "OK", strlen("OK"), 0, (struct sockaddr *)&servAddr, servAddrLen);
        memset(data, 0, sizeof(data));
    }
	/********** END **********/
	close(sockfd);	
	return 0;
}

基于TCP协议的Client/Server程序开发实例

第1关 服务器端程序开发

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

#define PORT 8888

int main()
{
	int sockfd;
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1)
	{
		return -1;
	}
	struct sockaddr_in addr;
	bzero(&addr, sizeof(addr));    //清空
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	//设置套接字属性
	int reuse = 1;
	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
	{
		perror("设置socket套接字错误\n");
		return "-1";
	}
	//与PORT端口进行绑定
	if(bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
	{
		return -1;
	}
	
	//监听PORT端口,并设置最大监听个数为5
	if(listen(sockfd, 5) == -1)
	{
		return -1;
	}
	
	int clientSockfd;
	struct sockaddr_in clientAddr;
	socklen_t clientAddrSize = sizeof(struct sockaddr_in);
	int pid;
	while(1)
	{
		//接受连接请求
		if((clientSockfd = accept(sockfd, (struct sockaddr *)&clientAddr, &clientAddrSize)) == -1)
		{
			return -1;
		}
		else
		{
			//接收客户端传来的数据,同时将接收到的数据原样发送给客户端
			/********** BEGIN **********/
			pid = fork();
            if(pid == -1)
            {
                printf("创建进程失败(%s)\n", strerror(errno));
                return -1;
            }
            else if(pid == 0)
            {
                //子进程
                close(sockfd);   //关闭服务器套接字
                char userInput[100];
                memset(userInput, 0, sizeof(userInput));
                while(recv(clientSockfd, userInput, sizeof(userInput), 0) > 0)
                {
                    if(strcasecmp(userInput, "exit") == 0)
                        break;
                    printf("%s\n", userInput);
                    send(clientSockfd, userInput, strlen(userInput), 0);  //发送数据
                    memset(userInput, 0, sizeof(userInput));  //清空上次接收的缓存
                }
                close(clientSockfd);  //关闭客户端连接
            }
            else
            {
            //父进程
                close(clientSockfd);  //关闭客户端连接
            }
        /********** END **********/
		}
	}
	close(sockfd);
	return 0;
}

第2关 基于TCP协议的文件上传下载工具开发

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

//定义服务器端口
#define PORT 8889

void *downloadFileServer(void *arg)
{
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1)
	{
		printf("创建TCP套接字失败: %s\n", strerror(errno));
		return "-1";
	}
	struct sockaddr_in addr;
	bzero(&addr, sizeof(addr));    //清空
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	//设置套接字属性
	int reuse = 1;
	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
	{
		perror("设置socket套接字错误\n");
		return "-1";
	}
	//绑定本地8889端口
	if(bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
	{
		printf("绑定端口失败: %s\n", strerror(errno));
		return "-1";
	}

	//监听8889s口,并设置最大监听个数为10
	if(listen(sockfd, 10) == -1)
	{
		printf("监听端口%d失败: %s\n", PORT, strerror(errno));
		return "-1";
	}

	//存放客户端主机信息
	struct sockaddr_in clientAddr;
	int clientAddrLen = sizeof(clientAddr);
	int clientSockfd;
	pid_t pid;
	while(1)
	{
		//监听客户端连接请求
		if((clientSockfd = accept(sockfd, (struct sockaddr *)&clientAddr, &clientAddrLen)) == -1)
		{
			printf("接受客户端请求失败: %s\n", strerror(errno));
			return "-1";
		}
		else
		{
			/********** BEGIN **********/
            char downLoadFileName[100];
            char data[16];
            pid = fork();
            if(pid == -1)
            {
                printf("创建进程失败(%s)\n", strerror(errno));
                return "-1";
            }else if(pid == 0){
                close(sockfd); //关闭服务器套接字
                recv(clientSockfd, downLoadFileName, sizeof(downLoadFileName), 0);
                send(clientSockfd, downLoadFileName, strlen(downLoadFileName), 0);
                int fd = open(downLoadFileName, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 
                int recvLen;
                memset(data, 0, sizeof(data));
                while((recvLen = recv(clientSockfd, data, sizeof(data),0)) > 0)
                {
                    if(data[0] == 'c')
                    {
                        write(fd, &(data[1]), recvLen - 1);
                        send(clientSockfd, "OK", strlen("OK"), 0);
                    }
                    else
                    {
                        close(fd);  //关闭文件
                        break;
                    }
                    memset(data, 0, sizeof(data));
                    }
                close(clientSockfd);
            }else{
                close(clientSockfd); 
            }
			/********** END **********/
		}
	}	
	close(sockfd);
	return "0";
}

交叉编译busybox

第1关 交叉编译工具的安装

apt-get update
apt-get install gcc-arm-linux-gnueabi
arm-linux-gnueabi-gcc -v

第2关 宿主机上编译BusyBox

apt-get install libncurses5-dev
cd /data/workspace/myshixun/
tar -jxvf busybox-1.2.2.tar.bz2
make menuconfig
依次进入Busybox Settings(设置选项),编译(Build Options),选中编译为静态库(Build BusyBox as a static binary (no shared libs)) 用Y选中
设置Shell (Shells),选择ash
执行命令完成编译:make
运行Busybox命令格式如下:./busybox 命令
运行如下命令,观察执行结果
./busybox
./busybox echo hello world
预期输出:
hello busybox

第3关 交叉编译运行BusyBox

(1)通过如下命令设置清除前期宿主机上的编译结果文件:make clean

(2)设置交叉编译工具前缀选项
使用如下命令配置BusyBox编译选项:make menuconfig
依次进入BusyBox设置(BusyBox Setting),编译选项(Build Option)中选择“是否使用交叉编译器?”(Do you want to build BusyBox with a Cross Compile ”),并将交叉编译器前缀设置为arm-linux-gnueabi-
(3)根据需要配置BusyBox的工具选项:在busybox中编译编辑工具vi
(4)使用如下命令完成交叉编译:make
(1)使用如下命令直接运行BusyBox
./busybox echo ‘hello busybox’
能看到ps命令的执行结果吗?看不到
(2)使用如下命令利用QEMU仿真器运行busybox
qemu-arm -L /usr/arm-linux-gnueabi -cpu cortex-a15 busybox echo ‘hello busybox’
(3)仿真器中运行busybox中的vi工具
qemu-arm -L /usr/arm-linux-gnueabi -cpu cortex-a15 busybox vi

标签:return,addr,int,编程,头歌,Linux,sockfd,include,struct
来源: https://blog.csdn.net/qq_43885168/article/details/117068125

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有