一、面试
自从毕业来公司已经有一年多了,也该总结一下这段时间的经历了。当初,抱着试一试的心态投了这家公司(比较有名气),结果第二天就去参加面试,总共进行了四轮,上午两轮,下午两轮。
第一轮是人力资源部的人面试,简单了解下个人的情况,也简单地介绍了公司的整体情况,过了一会儿,又有个人出来面我,这个人就是我现在的部门经理,聊了聊关于技术方面的,问了我大学期间都做了什么、做过的项目(当然是简单的小玩意儿)用到了哪些技术等,勉强答过去了。后来又问了一个关于数据库复杂查询的SQL语句,其实他刚一说出口,我就大概有个思路了,但是由于紧张愣是写错了。幸运的是,经理选择了相信我。让我有些不满意的是,经理是安徽人,说话声音特别小还特别快,让本来紧张的我更加紧张了,有时候完全跟不上他的节奏啊~到了中午,经理说先去吃饭,让我下午一点再过来。
就这样,在外面随便找了个小饭馆吃点东西,吃完后赶紧回去等着,生怕错过面试,其实还是比较喜欢这家公司的。过了一会儿,一个面带笑容的老工程师来面试我,主要就是谈一些对于.Net的理解以及设计和架构方面的知识,如面向对象、多态等。这一轮感觉自我良好,于是就来到了最后一轮的面试,这一轮给我面试的是这个部门的总监,聊天的时候发现那种紧张感消失了,可能是上一轮放的比较开。然后,他给我简单介绍了这个部门的业务、以及产品,谈话的过程中明显能感觉到他的领导风范和气场。最后问了下我的期望薪资,他给我的回复是只会比期望的高并且让我回去等通知,让我在回去的路上高兴的不得了,毕竟是第一份工作。
等待的过程是最痛苦的,过了第四天还没有消息,本来打算放弃了,但是我告诉自己再坚持一天,就这样,到了第七天才收到offer,那种兴奋的情绪到现在还记忆犹新。
二、初出茅庐
正值8月盛夏时节,坐在宽敞明亮的办公室的我感觉一段新的人生即将开始,想着想着,我的第一个任务来了,就是做调研。
其实做调研的过程就是熟悉行业动态和公司业务的过程,再此期间,我查阅了许多资料来充实我的调研报告,包括公司产品的横向对比,各自的优势和劣势等。这只是两个试用期任务中的一个。另一个任务是开发一个web上的word对比工具,对于刚毕业的我来说,这还是比较有难度的,但是也不能说因为难就不做,于是找到了一个开源的比较文本的组件加到项目中(开源只能帮我到这里了),接下来的一段时间里做剩余的补码工作,中间有过几次返工,因为无视需求,想当然地做,当然会返工。最后终于在不断修改和完善中完成了这个小项目。随后项目组给我分配了一个系统中的小模块,现在看来也是比较简单的,给定需求,参考已有的代码新建一个模块,数据库要自己设计,因为第一次参与项目,比较激动,同时很害怕出错,就请教了同事关于库的设计和后台代码有没有什么特别的要求,我得到的回复是尽量不用服务器端控件,在此之前也了解一点关于微软的服务器端控件封装的很好,同时也很臃肿,影响页面执行效率。于是我就开始了读源码,学习源码并开始写代码。读代码的过程是有些痛苦的,因为项目采用的是传统的WebForm加上三层架构搭建的,前台页面的代码乱的,你懂的,再看后台,几乎很少有注释,读着也是有些吃力,不过我参照的部分还算可以。中间遇到了一些问题,纠结了一阵,但是当成功的时候,发现那些付出真的是值得的。就这样做了将近2个月,这块基本完成了,但是BUG一定是有的(后期都已经清理了)。项目验收,在会议室演示的时候,基本满足需求,功能基本可用。回到办公室后,一个同事对我说我做的不错,其实好不好我心里还是比较清楚的,毕竟刚刚参与集体的大型项目,但是这句鼓励的话给了我很大的动力,此时已是接近年关。
三、水煮青蛙
年后回来后,部门还没有人给我安排新的任务,只是维护原来系统的Bug,基本上没有新的任务,每天也有很多的空闲时间,起初觉得还不错,有足够的时间供自己自由支配,但是我错了... ...
随着时间的推移,我已经拥有了大量的自由支配的时间,本来觉得这是件好事,这样就可以有自己的时间来学习充电了,但是,这时间不是一周两周那样的空闲,而是按月来计算,每天看着大家都在忙碌着,而我也在忙碌,但是总觉得心里不踏实,这种不踏实源于我没有为公司付出我的价值。其实这也和我自身有关,由于不是正八经的计算机软件工程专业出身(基本靠自己学习),使得我有一种自卑感,这种自卑源于对自身技术的不自信,总是害怕把事情做砸,所以我总是有些畏首畏尾,总是期待上面给我分配符合我个人能力的任务,但又不敢于去主动冒险。而部门经理也是很久才会问我一些工作的问题,基本上都是“最近在忙什么?”,平时基本上不会和我们谈心,可能是他个人的工作习惯吧,也没有机会诉说心里的一些想法,时间久了觉得很是压抑。突然发现这样下去,我只会更加沉迷于这种安逸的环境,更加地不踏实,逐渐丧失自己担当大任的勇气。趁着还年轻,多经历一些,跳出这个让人迷恋的“安乐窝”。让自己跟随自己的内心,因为我知道我想要的是什么,是时候让自己接受暴风雨的洗礼了。
四、写在最后
虽然有另谋高就的打算,但是我依然很感激现在这家公司,因为他是我的职业生涯中第一个平台,他接纳了这个刚刚毕业初入社会的小毛孩,让我有一个机会来展示自己,让我有一个机会来成熟自己;也很感谢我的项目经理,当初他完全可以因为我的一个SQL语句问题不要我,但是他没有,他选择了给我机会,我真的很感激。感谢那些曾经帮助过我、关心过我的同事们,和你们在一起的日子,真的很快乐。
在接下来的日子里,我会更加努力学习新技术,提升个人的核心竞争力,带着一颗感恩的心面对以后的生活。也希望迷茫的你,找到自己的方向,并狂奔下去... ...
作者:湫� �箜
博客地址:http://www.cnblogs.com/xhb-bky-blog/p/4167862.html
声明:本博客原创文字只代表本人工作中在某一时间内总结的观点或结论,与本人所在单位没有直接利益关系。非商业,未授权贴子请以现状保留,转载时必须保留此段声明,且在文章页面明显位置给出原文连接。
本文链接:【经历】总结下我一年来的工作经历,转载请注明。
上一篇 我们学习了简单的 Python TCP Socket 编程,通过分别写服务端和客户端的代码了解基本的 Python Socket 编程模型。本文再通过一个例子来加强一下对 Socket 编程的理解。
聊天室程序需求
我们要实现的是简单的聊天室的例子,就是允许多个人同时一起聊天,每个人发送的消息所有人都能接收到,类似于 QQ 群的功能,而不是点对点的 QQ 好友之间的聊天。如下图:
图来自:http://www.ibm.com/developerworks/linux/tutorials/l-pysocks/
我们要实现的有两部分:
- Chat Server:聊天服务器,负责与用户建立 Socket 连接,并将某个用户发送的消息广播到所有在线的用户。
- Telnet Client:用户聊天客户端,可以输入聊天的内容并发送,同时可以显示其他用户的消息记录。
同样,我们的消息通信采用 TCP 连接保证可靠性。在分别对服务端和客户端进行程序设计之前,首先要学习一下 Python 中实现异步 I/O 的一个函数 —— select
。
Python 异步 I/O
Python 在 select
模块中提供了异步 I/O(Asynchronous I/O),这与 Linux 下的 select 机制相似,但进行一些简化。我首先介绍一下 select
,然后告诉你在 Python 中如何使用它。
前面文章使用多线程来并行处理多路 socket I/O,这里介绍的select
方法允许你响应不同 socket 的多个事件以及其它不同事件。例如你可以让 select
在某个 socket 有数据到达时,或者当某个 socket 可以写数据时,又或者是当某个 socket 发生错误时通知你,好处是你可以同时响应很多 socket 的多个事件。
Linux 下 C 语言的 select
使用到位图来表示我们要关注哪些文件描述符的事件,Python 中使用 list 来表示我们监控的文件描述符,当有事件到达时,返回的也是文件描述符的 list,表示这些文件有事件到达。下面的简单程序是表示等待从标准输入中获得输入:
rlist, wlist, elist = select.select( [sys.stdin], [], [] )
print sys.stdin.read()
select
方法的三个参数都是 list 类型,分别代表读事件、写事件、错误事件,同样方法返回值也是三个 list,包含的是哪些事件(读、写、异常)满足了。上面的例子,由于参数只有一个事件 sys.stdin
,表示只关心标准输入事件,因此当 select
返回时 rlist 只会是 [sys.stdin]
,表示可以从 stdin 中读入数据了,我们使用 read
方法来读入数据。
当然 select
对于 socket 描述符也是有效的,下面的一个例子是创建了两个 socket 客户端连接到远程服务器,select
用来监控哪个 socket 有数据到达:
import socket
import select
sock1 = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
sock2 = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
sock1.connect( ('192.168.1.1', 25) )
sock2.connect( ('192.168.1.1', 25) )
while 1:
# Await a read event
rlist, wlist, elist = select.select( [sock1, sock2], [], [], 5 )
# Test for timeout
if [rlist, wlist, elist] == [ [], [], [] ]:
print "Five seconds elapsed.\n"
else:
# Loop through each socket in rlist, read and print the available data
for sock in rlist:
print sock.recv( 100 )
好了,有了上面的基础,我们就可以来设计聊天室的服务器和客户端了。
聊天室服务器
聊天室服务器主要完成下面两件事:
- 接收多个客户端的连接
- 从每个客户端读入消息病广播到其它连接的客户端
我们定义一个 list 型变量 CONNECTION_LIST
表示监听多个 socket 事件的可读事件,那么利用上面介绍的我们的服务器使用 select
来处理多路复用 I/O 的代码如下:
# Get the list sockets which are ready to be read through select
read_sockets,write_sockets,error_sockets = select.select(CONNECTION_LIST,[],[])
当 select
返回时,说明在 read_sockets
上有可读的数据,这里又分为两种情况:
- 如果是主 socket(即服务器开始创建的 socket,一直处于监听状态)有数据可读,表示有新的连接请求可以接收,此时需要调用
accept
函数来接收新的客户端连接,并将其连接信息广播到其它客户端。 - 如果是其它 sockets(即与客户端已经建立连接的 sockets)有数据可读,那么表示客户端发送消息到服务器端,使用
recv
函数读消息,并将消息转发到其它所有连接的客户端。
上面两种情况到涉及到广播消息的过程,广播也就是将从某个 socket 获得的消息通过 CONNECTION_LIST
的每个 socket (除了自身和主 socket)一个个发送出去:
def broadcast_data (sock, message):
#Do not send the message to master socket and the client who has send us the message
for socket in CONNECTION_LIST:
if socket != server_socket and socket != sock :
try :
socket.send(message)
except :
# broken socket connection may be, chat client pressed ctrl+c for example
socket.close()
CONNECTION_LIST.remove(socket)
如果发送失败,我们假设某个客户端已经断开了连接,关闭该 socket 病将其从连接列表中删除。
完整的聊天室服务器源代码如下:
没有评论:
发表评论