华清远见-学习之星活动

发布于:2023-01-21 ⋅ 阅读:(458) ⋅ 点赞:(0)

22061


一、本周的学习感受

        首先,本周因为换了一个新的讲师,对我来说又要适应新讲师的讲课速度,风格和习惯,但是我认为新讲师的讲课风格还是挺对我胃口的,我接受的比较快;

        本周学习的内容是网络编程的基础。虽然说是基础,但对于第一次接触的我来说,想要学会,依旧是一项不小的挑战,另外还需要结合前面所学习的知识,难度也是直线型上升,但这也是对前面所学的一种复习和巩固。


二、我所遇到的问题和解决的方法

传输多个参数

        在写多进程多线程tcp服务端时,写出来的程序只有在连接端口时看到IP和port号,看不出发送者的IP和port号,意思是只能知道谁连接了,但不是不知道谁发送了消息。

        所以我想到了在接收程序上发送者的IP地址和port号;在多进程tcp服务端,只需要多传入cli的地址就行,因为子进程可以传入多个参数;但是在多线程只能传入一个参数,就不得不使用结构体函数;

        但是我对线程传入结构体参数并不是很熟练,尝试了很多次,终于在不断的试错中完成了此程序;其中最让人难以捉摸的错误是:编译没有问题,但是一连接,出来显示连接成功以外,还会显示“Bad file descriptor”

                        ​​​​​​​        ​​​​​​​        

        反复调试后,则显示“Socket operation on non-socket”

        真是让初学者非常焦躁。后来想到可能是监听在不断的循环中达到上限,或者是反反复复的强转,让文件符号出现错误;

        总而言之,在我的尝试下还是取得了成功。这就是所谓的要理论结合实践吧。

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

struct cv{
	int cd;
	struct sockaddr_in ci;
};

void *rs(void *arg)
{
	struct cv *g = (struct cv *)arg;
	int cfd = g->cd;
	struct sockaddr_in cli = g->ci;
	ssize_t recv_bytes,send_bytes;
	char buf[128] = {0};
	while(1)
	{ 	memset(buf,0,sizeof(buf));
		recv_bytes = recv(cfd,buf,sizeof(buf),0);
		if(recv_bytes == -1)
		{ 	perror("cuowu4");
			break; 	}
		else if (recv_bytes == 0)
			break;
		printf("(%s|%d): %s\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port),buf); 	
		send_bytes = send(cfd,buf,recv_bytes,0);

		if(send_bytes == -1)
		{ 	perror("cuowu5");
			break; 	} 	}
	close(cfd);
	pthread_exit(NULL);
} 

int main(int argc, const char *argv[])
{
	if(argc < 3)
	{ 	perror("cuowu0");
		return -1; 	}

	int sfd,ret,cfd,ff;
	pthread_t tid;
	struct sockaddr_in src,cli;

	sfd = socket(AF_INET,SOCK_STREAM,0);
	socklen_t len = sizeof(src);
	socklen_t addrlen = sizeof(cli);
	if(sfd == -1)
	{ 	perror("cuowu1");
		return -1; 	}
	
	src.sin_family = AF_INET;
	src.sin_port = htons(atoi(argv[2]));
	src.sin_addr.s_addr = inet_addr(argv[1]);

	bind(sfd,(const struct sockaddr *)&src,len);
	
	ret = listen(sfd,1024);
	if(ret == -1)
	{ 	perror("cuowu2");
		return -1; 	}
	
	while(1){
	cfd = accept(sfd,(struct sockaddr *)&cli,&addrlen);
	if(cfd == -1)
	{ 	perror("cuowu3");
		return -1; 	}
	struct cv *p = (struct cv*)malloc(sizeof(struct cv));
	p->cd = cfd;
	p->ci = cli;


	printf("(%s|%d): 连接成功\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port)); 	
	ff = pthread_create(&tid,NULL,rs,(void*)p);
	if (ff != 0)
	{ 	errno  = ff;
		perror("cuowu6");
		return -1; 	} 	
	pthread_detach(tid); 	}
 	

	return 0;
}


学习成果

        对于这一周的学习,我认为还是有一点成果的。不仅了解了许多网络相关的知识点,比如:

        生活中关于网络的硬件,像是网卡,路由器,交换机之类的;什么是局域网和广域网;IP,端口号,子网掩码,网管,DNS,DHCP和它们直接的转换关系;网络通讯的原理,路由器和交换机的原理,OSI模型,包括物理层,数据链路层,网络层,传输层,会话层,表示层和应用层;

        然后最主要的就是了解了udp服务器和客户端,tcp服务器和客户端的原理,及其一些编程; 

        udp相比较于tcp,是不可靠的,但是速度较快;tcp服务端于客户端在建立连接是要握手三次,断开时还需要挥手四次,确保数据无丢失和失序,这就是其可靠性;

        设计的流程都是先建立socket,在绑定IP地址和端口号,tcp多一步建立监听队列,然后再是数据的接收和发送。

        最后学到了多进程多线程的并发服务器,虽然说比之前难上一些,但是却可以让我重温之前学到的许多知识,必然是一种磨炼。

        可以说这一周我的学习收货还是很多的,学习必然是会有收货的,因为每个人自然都不会嫌自己的知识储备量太多。


网站公告

今日签到

点亮在社区的每一天
去签到