|
作者简介: Eric Sink,SourceGear创始人,是Eric Sink on the Business of Software的作者。他还是AbiWord项目的发起者。在这之前,他在SpyGlass工作,领导浏览器开发工作,其代码后来授权给了微软并成为早期IE浏览器的基础。 下面的文章来自Eric的个人blog。这是一个很有意思的系列文章,对于中国程序员来说,这也许是一个很多人感兴趣,却很少有人讨论的领域。我计划在今后以每周2篇的速度发出来。由于这也是我第一次翻译东西,如果有人发现不对或不妥的地方还请指正。转载请注明原作者和译者。我的邮箱: iamzhutuo@gmail.com。 下面开始是正文了。 原文链接 技术工作者如何进行市场营销本页是我的系列文章《技术工作者如何进行市场营销》的目录,这个系列的中心思想是,如果我们不刻意去神秘化市场营销工作,技术工作者完全有能力胜任它。这是一个正在创作中的系列,新的内容会在不久后添加进来。 [译者注:本文是2003年7月30日写作的, 这个系列现在已经完成了, 后面我会尽量把他们都翻译出来.] 在很多小的独立软件开发公司里,很重要的一点是至少有一部分开发人员要懂得基本的市场营销知识。但是,由于缺乏创新能力和图形设计的能力,很多技术工作者对市场营销工作有着逃避的情绪。但这些都不是判断一个市场从业人员合格与否的决定性因素。市场营销的成功与否主要取决于策略,而非艺术设计。事实上,很多团队能够提升市场营销水平,主要是因为他们了解到市场工作,就像软件研发一样,有两个完全不同的阶段。 市场营销的两个阶段 当我们开发一款软件,我们通常会有设计阶段,以及随后的实施阶段。在设计阶段,我们仔细评估我们想要做的是什么;在实现阶段,我们按需求完成它。 同样的,市场营销有一个策划阶段,和一个传播阶段。 - 策划阶段类似软件研发中的设计阶段。(事实上,它们是相关而且通常必须共同完成的。)
传播阶段类似于软件研发的实现阶段。我们称这一系列的活动为“营销传播”,或者简称为"marcomm"。
一个有趣的事实是,尽管市场工作者和软件开发人员通常认为彼此没什么共同点,这两个团队都会自然地试图跳过它们的第一阶段。标新立异的程序员们不想写需求和设计文档。他们只想直接开始写代码。类似地,市场工作者也倾向于一头扎进写宣传文案,做广告宣传等工作。在这两者中,跳过第一阶段会为你带来立竿见影的工作成果,但是你会在接下来的工作中遇到形形色色的问题。 关于策略的文章:产品管理 (2008.10.22)浸信会和边界 (2007.1.19)在我住的小区里,所有的人都需要至少300英尺深的一口井。根据这一事实,我推断这个区域内钻井业将会有很好的前途。但是,城市的供水系统就在3英里之外。这个例子看上去很蠢,但是在这个时候,很多公司都在根据类似的逻辑写着他们的商业计划。
怎样让人们都谈论你的产品(2006.8.24)口口相传不是一种策略,它是策略的结果。我们如何使之成为现实?
游戏变得不对劲了(2005.7.12)我们都理解编程中的深度抽象和面向对象。我们也都能明白虚拟内存是如何工作的。我们当中还有些人能记住vi里如何搜索和替换。但是当技术宅们开始谈论如何市场中什么样的软件才有竞争力时,通常看起来很有头脑的我们就变得像帕里斯希尔顿一样了。我们就是不明白这一点。技术工作者对市场营销工作的理解就像男人对女人的理解一样。
技术工作者的心理障碍 (2003.8.7)想要接触主流的消费者,有些时候我们需要忽略我们个人的喜好,而去做真正的消费者们想做的。市场营销工作中的非技术人员能很好的做到这一点。一旦他们确定了市场需要的是什么,他们就会全力以赴把这样的产品送到消费者手中。他们不会对实现它的技术有任何看法,也就能毫不费力地区分消费者的需求和自己的喜好。
在产品生命周期中的每一步,做好该做的事(2003.7.9)但是第三步是无论如何都会发生在你的产品上的。就像是正常人类所必然经历的老化过程,我们的产品也会经历生命周期中的各个阶段。唯一能避免进行到下一阶段的方式就是死亡,所以我们必须优雅的面对这些阶段。
市场营销不是预处理 (2003.6.6)“市场营销不仅仅是向整个世界介绍你的产品。市场营销还包括产品特性的确定。你需要设计并开发出符合预期市场定位的产品”
选择你的对手 (2003.4.4)很重要的一点就是选择你期望的竞争对手。我喜欢Jim Barksdale的选择竞争对手的哲学:选一个“大而蠢”的对手。
关于“Marcomm” 的文章参加一个贸易展 (2004.5.28)贸易展是我个人最喜爱的“marcomm”工具,因为它是互动的。广告和PR是你向你的客户单向的投放,信息没有机会从对方流向你。其他的marcomm工具也各有各的用途,但是没有像贸易展一样有效的。
小独立软件开发商的杂志广告指南 (2003.5.1)对小的独立开发商来说,登广告不是一个合理使用资金的途径。举例来说,在主流软件开发杂志上登一个整版彩页的广告可能会花掉超过10000美元。你要卖掉多少份软件才能付得起广告的费用?老实说,买10000张彩票都可能是更好的投资选择。
http://www.zhihu.com/question/19931404 http://wenku.baidu.com/view/78898a1fa76e58fafab00377.html http://www.cnblogs.com/xiaoxuanzi/tag/%E7%B2%BE%E9%80%9Agit/
%a 浮点数、十六进制数字和p-记数法(C99)
%A 浮点数、十六进制数字和p-记法(C99)
%c 一个字符
%d 有符号十进制整数
%e 浮点数、e-记数法
%E 浮点数、E-记数法
%f 浮点数、十进制记数法
%g 根据数值不同自动选择%f或%e.
%G 根据数值不同自动选择%f或%e.
%i 有符号十进制数(与%d相同)
%o 无符号八进制整数
%p 指针
%s 字符串
%u 无符号十进制整数
%x 使用十六进制数字0f的无符号十六进制整数
%X 使用十六进制数字0f的无符号十六进制整数
%% 打印一个百分号
Posted by Matthew E under Code Editors, Productivity, Programming, SlickEdit Products [3] Comments Whenever we’re putting together marketing materials, advertising copy, checklists of features to demo at trade shows, etc, a common start of the conversation is “What are the top features of SlickEdit”. Feature lists are all well and good, but just because we think a feature makes a Top Ten list doesn’t mean it resonates with every user. And features are usually spoken of in broad brush strokes, like “Version Control Integration” or “Configurable Keyboard Emulations”. But what really makes your editor an indispensable tool is the collection of small features and tricks that you use every day. And there is no Top Ten list that covers this, as everyone’s list is different. We did a quick poll around the office to gather up some of the features that we use all the time. And yes, everyone’s list was quite different. So in no particular order, here are a few of our favorite things in SlickEdit. Italic bold below denotes a Slick-C command, like complete-next, which can be executed from the SlickEdit command line or bound to a keyboard shortcut. complete-next and complete-prev Bound to Ctrl+Shift+> and Ctrl+Shift+< in most emulations. This searches for prefix matches in your current document. Very handy for completing words when you’re working in plain text or in a file format where Context Tagging is not able to provide symbol matches, or when you want to pick up non-symbol matches, like words found inside comments. where-is, what-is, and bind-to-key For those of you who like to keep your hands on the keyboard as much as possible, you need this. Sure this information is available on the menus and in the Options dialog, but why mouse around? Entering where-is on the SlickEdit command line will allow you to enter a Slick-C command to see if there’s a keyboard shortcut defined for it, while what-is lets you see the command name for a shortcut, or check if it’s free. Use bind-to-key to define a shortcut for something that’s currently not bound to one. Aliases with %\n If we had to list which features of SlickEdit we feel are underutilized outside our office walls, Aliases would be at the top of every list. Aliases simply allow you to type a short sequence which will be expanded, which is great for frequently used boilerplate text. They can be defined globally or on a per-language basis. We do provide some aliases out-of-the-box, but the real power is in creating your own. Go to the Tools > Options dialog, and search for “Aliases” to see where you can define them. A common usage is generating “Caveman Debugging” statements. Here’s a sample alias for C. printf(" %\n: %\c \n"); The SlickEdit alias facility has several escape sequences, and %\n is the sequence for “current function name”, and %\c positions the cursor for editing after the text expansion is made. toggle-comment This feature originated as a macro written by one of our customers, which he shared on our community forums. It was so popular that we made it part of the product. It’s a great complement to comment-lines and comment-block. Quick replacements from the command line Doing a quick search and replace inside the current file is a snap using the c/old/new/ syntax on the command line. Even more power comes from using command modifiers after the trailing slash. For example, the ‘m’ modifier means ‘mark’ (our term for current selection), and ‘*’ means globally without confirmation prompting. So to change all instances of char to wchar_t in your current selection without a prompt, you would enter c/char/wchar_t/m* on the command line, and you’re done. svc-diff-with-tip This is a super-quick way to compare your current file with the most recent version in version control, bypassing the version control history dialog. This currently supports CVS, Subversion, and Git. And if you’re using Subversion, and not currently able to connect to the repository, svn-diff-with-base performs a comparison with the ‘clean’ copy from your most recent update. svn-get-annotated-buffer and cvs-get-annotated-buffer A wrapper around the “blame” command for CVS and Subversion. Warning: May be habit-forming. list-buffers and project-load These bring up the Files tool window. Stop right there! You’re about to skip past this one because the word “Files” is pretty plain, and “bring up the Files tool window” sounds pretty dull. Do yourself a favor and try them out, and perhaps set up keyboard bindings for them. list-buffers will show you a searchable list of all the files you currently have open, allowing you to quickly switch to one without having to search through file tabs. Handy if you tend to leave a lot of files open in the editor. If you have a project open, the Project and Workspace tabs of the Files window allow you to find any file and open it from there. Very helpful for large projects. Vim cursor keys I hesitated to include this one initially. It’s not specific to SlickEdit, of course, and is only one of the 15 keyboard emulations we define. But if you’re a vi/vim adherent, having a high fidelity vim emulation built into your IDE is a big deal. It allows you to get all the benefits of the tools and features built into the environment without having to rewire you brain when you actually need to edit code. If you’ve ever accidently typed a stray ‘j’, ‘h’, or ‘dd’ or into an instant messaging client, you know exactly what I mean. What feature(s) is/are highest on your list?
http://feeds.feedburner.com/helloWorld-TheSlickeditDeveloperBlog
- Alt + Enter -- 全屏
- Alt + B --打开新的连接
- Alt + 1/2/3/4/5.../9 -- 切换到第1/2/3/4/5.../9个标签
-
- Ctrl + A -- 光标移至行首。
- Ctrl + B -- 光标前移1个字符
- Ctrl + D -- 删除光标后1个字符
- Ctrl + E -- 光标移至行末
- Ctrl + F -- 光标后移1个字符
- Ctrl + H -- 删除光标前的1个字符
- Ctrl + J -- 回车
- Ctrl + k -- 删除当前光标至行末的字符
- Ctrl + P -- 显示前一条命令
- Ctrl + M -- 回车
- Ctrl + N -- 下一条命令
- Ctrl + T -- 交换光标前最后两个字符(思科路由器可用)
- Ctrl + U -- 清除当前行和缓存的输入
- Ctrl + V -- 输入ctrl字符
- Ctrl + W -- 删除当前光标至行首的字符
二、实验平台 Linux操作系统 三、实验内容 编写Linux下TCP服务器套接字程序,程序运行时服务器等待客户的连接,一旦连接成功,则显示客户的IP地址、端口号,并向客户端发送字符串。 四、实验原理 使用TCP套接字编程可以实现基于TCP/IP协议的面向连接的通信,它分为服务器端和客户端两部分,其主要实现过程如图1.1所示。
图1.1 TCP客户/服务器的套接字函数 1、socket函数:为了执行网络输入输出,一个进程必须做的第一件事就是调用socket函数获得一个文件描述符。 ----------------------------------------------------------------- #include <sys/socket.h> int socket(int family,int type,int protocol); 返回:非负描述字---成功 -1---失败 ----------------------------------------------------------------- |
第一个参数指明了协议簇,目前支持5种协议簇,最常用的有AF_INET(IPv4协议)和AF_INET6(IPv6协议);第二个参数指明套接口类型,有三种类型可选:SOCK_STREAM(字节流套接口)、SOCK_DGRAM(数据报套接口)和SOCK_RAW(原始套接口);如果套接口类型不是原始套接口,那么第三个参数就为0。 2、connect函数:当用socket建立了套接口后,可以调用connect为这个套接字指明远程端的地址;如果是字节流套接口,connect就使用三次握手建立一个连接;如果是数据报套接口,connect仅指明远程端地址,而不向它发送任何数据。 ----------------------------------------------------------------- #include <sys/socket.h> int connect(int sockfd, const struct sockaddr * addr, socklen_t addrlen); 返回:0---成功 -1---失败 ----------------------------------------------------------------- |
第一个参数是socket函数返回的套接口描述字;第二和第三个参数分别是一个指向套接口地址结构的指针和该结构的大小。 这些地址结构的名字均已“sockaddr_”开头,并以对应每个协议族的唯一后缀结束。以IPv4套接口地址结构为例,它以“sockaddr_in”命名,定义在头文件<netinet/in.h>;以下是结构体的内容: ------------------------------------------------------------------ struct in_addr { in_addr_t s_addr; /* IPv4地址 */ }; struct sockaddr_in { uint8_t sin_len; /* 无符号的8位整数 */ sa_family_t sin_family; /* 套接口地址结构的地址簇,这里为AF_INET */ in_port_t sin_port; /* TCP或UDP端口 */ struct in_addr sin_addr; char sin_zero[8]; }; ------------------------------------------------------------------- |
3、bind函数:为套接口分配一个本地IP和协议端口,对于网际协议,协议地址是32位IPv4地址或128位IPv6地址与16位的TCP或UDP端口号的组合;如指定端口为0,调用bind时内核将选择一个临时端口,如果指定一个通配IP地址,则要等到建立连接后内核才选择一个本地IP地址。 ------------------------------------------------------------------- #include <sys/socket.h> int bind(int sockfd, const struct sockaddr * server, socklen_t addrlen); 返回:0---成功 -1---失败 ------------------------------------------------------------------- |
第一个参数是socket函数返回的套接口描述字;第二和第第三个参数分别是一个指向特定于协议的地址结构的指针和该地址结构的长度。 4、listen函数:listen函数仅被TCP服务器调用,它的作用是将用sock创建的主动套接口转换成被动套接口,并等待来自客户端的连接请求。 ------------------------------------------------------------------- #include <sys/socket.h> int listen(int sockfd,int backlog); 返回:0---成功 -1---失败 ------------------------------------------------------------------- |
第一个参数是socket函数返回的套接口描述字;第二个参数规定了内核为此套接口排队的最大连接个数。由于listen函数第二个参数的原因,内核要维护两个队列:以完成连接队列和未完成连接队列。未完成队列中存放的是TCP连接的三路握手为完成的连接,accept函数是从以连接队列中取连接返回给进程;当以连接队列为空时,进程将进入睡眠状态。 5、accept函数:accept函数由TCP服务器调用,从已完成连接队列头返回一个已完成连接,如果完成连接队列为空,则进程进入睡眠状态。 ------------------------------------------------------------------- #include <sys/socket.h> int accept(int listenfd, struct sockaddr *client, socklen_t * addrlen); 回:非负描述字---成功 -1---失败 ------------------------------------------------------------------- |
第一个参数是socket函数返回的套接口描述字;第二个和第三个参数分别是一个指向连接方的套接口地址结构和该地址结构的长度;该函数返回的是一个全新的套接口描述字;如果对客户段的信息不感兴趣,可以将第二和第三个参数置为空。 6、write和read函数:当服务器和客户端的连接建立起来后,就可以进行数据传输了,服务器和客户端用各自的套接字描述符进行读/写操作。因为套接字描述符也是一种文件描述符,所以可以用文件读/写函数write()和read()进行接收和发送操作。 (1)write()函数用于数据的发送。 ------------------------------------------------------------------- #include <unistd.h> int write(int sockfd, char *buf, int len); 回:非负---成功 -1---失败 ------------------------------------------------------------------- 参数sockfd是套接字描述符,对于服务器是accept()函数返回的已连接套接字描述符,对于客户端是调用socket()函数返回的套接字描述符;参数buf是指向一个用于发送信息的数据缓冲区;len指明传送数据缓冲区的大小。 (2)read()函数用于数据的接收。 ------------------------------------------------------------------- #include <unistd.h> int read(int sockfd, char *buf, intlen); 回:非负---成功 -1---失败 ------------------------------------------------------------------- 参数sockfd是套接字描述符,对于服务器是accept()函数返回的已连接套接字描述符,对于客户端是调用socket()函数返回的套接字描述符;参数buf是指向一个用于接收信息的数据缓冲区;len指明接收数据缓冲区的大小。 7、send和recv函数:TCP套接字提供了send()和recv()函数,用来发送和接收操作。这两个函数与write()和read()函数很相似,只是多了一个附加的参数。 (1)send()函数用于数据的发送。 ------------------------------------------------------------------- #include <sys/types.h> #include < sys/socket.h > ssize_t send(int sockfd, const void *buf, size_t len, int flags); 回:返回写出的字节数---成功 -1---失败 ------------------------------------------------------------------- 前3个参数与write()相同,参数flags是传输控制标志。 (2)recv()函数用于数据的发送。 ------------------------------------------------------------------- #include <sys/types.h> #include < sys/socket.h > ssize_t recv(int sockfd, void *buf, size_t len, int flags); 回:返回读入的字节数---成功 -1---失败 ------------------------------------------------------------------- 前3个参数与read()相同,参数flags是传输控制标志。 五、实验步骤 1、登陆进入ubuntu操作系统,新建一个文件,命名为tcpserver.c(为了方便起见,可以进入“home”,再进入用户目录,在用户目录下新建tcpserver.c)。 2、在tcpserver.c中编写服务器端程序代码并保存。 3、在“终端”(“Applications”→“附件”→“终端”)中执行命令进入tcpserver.c所在目录。(pwd命令可以显示当前所在目录;ls命令可以显示当前目录下的文件和文件夹信息;cd..命令可以进入上一级目录;cd 目录名 命令可以进入当前所示的某个目录。) 4、执行命令gcc –o tcpserver tcpserver.c生成可执行文件tcpserver。 5、执行命令./ tcpserver,观察结果。 6、认真分析源代码,体会如何编写一个TCP服务器端程序。 六、参考程序(tcpserver.c) - #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
-
- #define PORT 1234
- #define BACKLOG 1
-
- int main()
- {
- int listenfd, connectfd;
- struct sockaddr_in server;
- struct sockaddr_in client;
- socklen_t addrlen;
- if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- {
- perror("Creating socket failed.");
- exit(1);
- }
- int opt =SO_REUSEADDR;
- setsockopt(listenfd,SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
- bzero(&server,sizeof(server));
- server.sin_family=AF_INET;
- server.sin_port=htons(PORT);
- server.sin_addr.s_addr= htonl (INADDR_ANY);
- if(bind(listenfd, (struct sockaddr *)&server, sizeof(server)) == -1) {
- perror("Binderror.");
- exit(1);
- }
- if(listen(listenfd,BACKLOG)== -1){ /* calls listen() */
- perror("listen()error\n");
- exit(1);
- }
- addrlen =sizeof(client);
- if((connectfd = accept(listenfd,(struct sockaddr*)&client,&addrlen))==-1) {
- perror("accept()error\n");
- exit(1);
- }
- printf("Yougot a connection from cient's ip is %s, prot is %d\n",inet_ntoa(client.sin_addr),htons(client.sin_port));
- send(connectfd,"Welcometo my server.\n",22,0);
- close(connectfd);
- close(listenfd);
- return 0;
- }
实验二 TCP客户端程序设计 一、实验目的 学习和掌握Linux下的TCP客户端基本原理和基本编程方法。 二、实验平台 Linux操作系统 三、实验内容 编写Linux下TCP客户端套接字程序,结合实验一的服务器端程序,实现以下功能: 1、客户根据用户提供的IP地址连接到相应的服务器; 2、服务器等待客户的连接,一旦连接成功,则显示客户的IP地址、端口号,并向客户端发送字符串; 3、客户接收服务器发送的信息并显示。 四、实验原理 见实验一的实验原理部分。 五、实验步骤 1、登陆进入ubuntu操作系统,新建一个文件,命名为tcpclient.c(为了方便起见,可以进入“home”,再进入用户目录,在用户目录下新建tcpclient.c)。 2、在tcpclient.c中编写客户端程序代码并保存。将实验一完成的tcpserver.c拷贝到与tcpclient.c同一目录下。 3、在“终端”(“Applications”→“附件”→“终端”)中执行命令进入tcpserver.c和tcpclient.c所在目录。 4、执行命令gcc –o tcpserver tcpserver.c生成可执行文件tcpserver。 5、执行命令./ tcpserver。 6、再开一个“终端”,进入tcpserver.c和tcpclient.c所在目录,执行命令 gcc–o tcpclient tcpclient.c生成可执行文件tcpclient。 7、执行命令./ tcpclient 127.0.0.1。 8、观察两个“终端”出现的结果。 9、认真分析源代码,体会如何编写一个TCP客户端程序。 六、参考程序(tcpclient.c) - #include<stdio.h>
- #include <stdlib.h>
- #include<unistd.h>
- #include<string.h>
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<netinet/in.h>
- #include<netdb.h>
-
- #define PORT 1234
- #define MAXDATASIZE 100
-
- int main(int argc, char *argv[])
- {
- int sockfd, num;
- char buf[MAXDATASIZE];
- struct hostent *he;
- struct sockaddr_in server;
- if (argc!=2) {
- printf("Usage:%s <IP Address>\n",argv[0]);
- exit(1);
- }
- if((he=gethostbyname(argv[1]))==NULL){
- printf("gethostbyname()error\n");
- exit(1);
- }
- if((sockfd=socket(AF_INET, SOCK_STREAM, 0))==-1){
- printf("socket()error\n");
- exit(1);
- }
- bzero(&server,sizeof(server));
- server.sin_family= AF_INET;
- server.sin_port = htons(PORT);
- server.sin_addr =*((struct in_addr *)he->h_addr);
- if(connect(sockfd,(struct sockaddr *)&server,sizeof(server))==-1){
- printf("connect()error\n");
- exit(1);
- }
- if((num=recv(sockfd,buf,MAXDATASIZE,0)) == -1){
- printf("recv() error\n");
- exit(1);
- }
- buf[num-1]='\0';
- printf("Server Message: %s\n",buf);
- close(sockfd);
- return 0;
- }
-
实验结果:
二、实验平台 ubuntu-8.04操作系统 三、实验内容 编写Linux下UDP服务器套接字程序,服务器接收客户端发送的信息并显示,同时显示客户的IP地址、端口号,并向客户端发送信息。如果服务器接收的客户信息为“bye”,则退出循环,并关闭套接字。 四、实验原理 UDP套接口是无连接的、不可靠的数据报协议;既然他不可靠为什么还要用呢?其一:当应用程序使用广播或多播时只能使用UDP协议;其二:由于他是无连接的,所以速度快。因为UDP套接口是无连接的,如果一方的数据报丢失,那另一方将无限等待,解决办法是设置一个超时。 建立UDP套接口时socket函数的第二个参数应该是SOCK_DGRAM,说明是建立一个UDP套接口;由于UDP是无连接的,所以服务器端并不需要listen或accept函数。 使用UDP套接字编程可以实现基于TCP/IP协议的面向无连接的通信,它分为服务器端和客户端两部分,其主要实现过程如图3.1所示。
图3.1 UDP客户/服务器的套接字函数
1、socket函数:为了执行网络输入输出,一个进程必须做的第一件事就是调用socket函数获得一个文件描述符。 ----------------------------------------------------------------- #include <sys/socket.h> int socket(int family,int type,int protocol); 返回:非负描述字---成功 -1---失败 ----------------------------------------------------------------- |
第一个参数指明了协议簇,目前支持5种协议簇,最常用的有AF_INET(IPv4协议)和AF_INET6(IPv6协议);第二个参数指明套接口类型,有三种类型可选:SOCK_STREAM(字节流套接口)、SOCK_DGRAM(数据报套接口)和SOCK_RAW(原始套接口);如果套接口类型不是原始套接口,那么第三个参数就为0。
2、bind函数:为套接口分配一个本地IP和协议端口,对于网际协议,协议地址是32位IPv4地址或128位IPv6地址与16位的TCP或UDP端口号的组合;如指定端口为0,调用bind时内核将选择一个临时端口,如果指定一个通配IP地址,则要等到建立连接后内核才选择一个本地IP地址。 ------------------------------------------------------------------- #include <sys/socket.h> int bind(int sockfd, const struct sockaddr * server, socklen_t addrlen); 返回:0---成功 -1---失败 ------------------------------------------------------------------- |
第一个参数是socket函数返回的套接口描述字;第二和第第三个参数分别是一个指向特定于协议的地址结构的指针和该地址结构的长度。
3、recvfrom函数:UDP使用recvfrom()函数接收数据,他类似于标准的read(),但是在recvfrom()函数中要指明目的地址。 ------------------------------------------------------------------- #include <sys/types.h> #include <sys/socket.h> ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr * from, size_t *addrlen); 返回接收到数据的长度---成功 -1---失败 ------------------------------------------------------------------- |
前三个参数等同于函数read()的前三个参数,flags参数是传输控制标志。最后两个参数类似于accept的最后两个参数。
4、sendto函数:UDP使用sendto()函数发送数据,他类似于标准的write(),但是在sendto()函数中要指明目的地址。 ------------------------------------------------------------------- #include <sys/types.h> #include <sys/socket.h> ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr * to, int addrlen); 返回发送数据的长度---成功 -1---失败 ------------------------------------------------------------------- |
前三个参数等同于函数read()的前三个参数,flags参数是传输控制标志。参数to指明数据将发往的协议地址,他的大小由addrlen参数来指定。
五、实验步骤 1、登陆进入ubuntu操作系统,新建一个文件,命名为udpserver.c(为了方便起见,可以进入“home”,再进入用户目录,在用户目录下新建udpserver.c)。 2、在udpserver.c中编写服务器端程序代码并保存。 3、在“终端”(“Applications”→“附件”→“终端”)中执行命令进入udpserver.c所在目录。(pwd命令可以显示当前所在目录;ls命令可以显示当前目录下的文件和文件夹信息;cd..命令可以进入上一级目录;cd 目录名 命令可以进入当前所示的某个目录。) 4、执行命令gcc –o udpserver udpserver.c生成可执行文件udpserver。 5、执行命令./ udpserver,观察结果。 6、认真分析源代码,体会如何编写一个UDP服务器端程序。 六、参考程序(udpserver.c)
- #include<stdio.h>
- #include<string.h>
- #include<unistd.h>
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<stdlib.h>
- #include<netinet/in.h>
- #include<arpa/inet.h>
-
- #define PORT 1234
- #define MAXDATASIZE 100
-
- main()
- {
- int sockfd;
- struct sockaddr_in server;
- struct sockaddr_in client;
- socklen_t addrlen;
- int num;
- char buf[MAXDATASIZE];
-
- if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
- {
- perror("Creatingsocket failed.");
- exit(1);
- }
-
- bzero(&server,sizeof(server));
- server.sin_family=AF_INET;
- server.sin_port=htons(PORT);
- server.sin_addr.s_addr= htonl (INADDR_ANY);
- if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) == -1)
- {
- perror("Bind()error.");
- exit(1);
- }
-
- addrlen=sizeof(client);
- while(1)
- {
- num =recvfrom(sockfd,buf,MAXDATASIZE,0,(struct sockaddr*)&client,&addrlen);
-
- if (num < 0)
- {
- perror("recvfrom() error\n");
- exit(1);
- }
-
- buf[num] = '\0';
- printf("You got a message (%s%) from client.\nIt's ip is%s, port is %d.\n",buf,inet_ntoa(client.sin_addr),htons(client.sin_port));
- sendto(sockfd,"Welcometo my server.\n",22,0,(struct sockaddr *)&client,addrlen);
- if(!strcmp(buf,"bye"))
- break;
- }
- close(sockfd);
- }
实验四 UDP客户端程序设计 一、实验目的 学习和掌握Linux下的UDP客户端基本原理和基本编程方法。 二、实验平台 ubuntu-8.04操作系统 三、实验内容 编写Linux下UDP客户端套接字程序,结合实验三的UDP服务器端程序,实现以下功能: 1、客户根据用户提供的IP地址将用户从终端输入的信息发送给服务器,然后等待服务器的回应。 2、服务器接收客户端发送的信息并显示,同时显示客户的IP地址、端口号,并向客户端发送信息。如果服务器接收的客户信息为“bye”,则退出循环,并关闭套接字。 3、客户接收、显示服务器发回的信息,并关闭套接字。 四、实验原理 见实验三的实验原理部分。 五、实验步骤 1、登陆进入ubuntu操作系统,新建一个文件,命名为udpclient.c(为了方便起见,可以进入“home”,再进入用户目录,在用户目录下新建udpclient.c)。 2、在udpclient.c中编写客户端程序代码并保存。将实验三完成的udpserver.c拷贝到与udpclient.c同一目录下。 3、在“终端”(“Applications”→“附件”→“终端”)中执行命令进入udpserver.c和udpclient.c所在目录。 4、执行命令gcc –o udpserver udpserver.c生成可执行文件udpserver。 5、执行命令./ udpserver。 6、再开一个“终端”,进入udpserver.c和udpclient.c所在目录,执行命令 gcc–o udpclient udpclient.c生成可执行文件udpclient。 7、执行命令./ udpclient 127.0.0.1 hello。 8、观察两个“终端”出现的结果。 9、在客户端终端下执行命令./ udpclient 127.0.0.1 bye。 10、观察两个“终端”出现的结果。 11、认真分析源代码,体会如何编写一个UDP客户端程序。 六、参考程序(udpclient.c) - #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
-
- #define PORT 1234
- #define MAXDATASIZE 100
-
- int main(int argc, char *argv[])
- {
- int sockfd, num;
- char buf[MAXDATASIZE];
-
- struct hostent *he;
- struct sockaddr_in server,peer;
-
- if (argc !=3)
- {
- printf("Usage: %s <IP Address><message>\n",argv[0]);
- exit(1);
- }
-
- if ((he=gethostbyname(argv[1]))==NULL)
- {
- printf("gethostbyname()error\n");
- exit(1);
- }
-
- if ((sockfd=socket(AF_INET, SOCK_DGRAM,0))==-1)
- {
- printf("socket() error\n");
- exit(1);
- }
-
- bzero(&server,sizeof(server));
- server.sin_family = AF_INET;
- server.sin_port = htons(PORT);
- server.sin_addr= *((struct in_addr *)he->h_addr);
- sendto(sockfd, argv[2],strlen(argv[2]),0,(struct sockaddr *)&server,sizeof(server));
- socklen_t addrlen;
- addrlen=sizeof(server);
- while (1)
- {
- if((num=recvfrom(sockfd,buf,MAXDATASIZE,0,(struct sockaddr *)&peer,&addrlen))== -1)
- {
- printf("recvfrom() error\n");
- exit(1);
- }
- if (addrlen != sizeof(server) ||memcmp((const void *)&server, (const void *)&peer,addrlen) != 0)
- {
- printf("Receive message from otherserver.\n");
- continue;
- }
-
- buf[num]='\0';
- printf("Server Message:%s\n",buf);
- break;
- }
-
- close(sockfd);
- }
UDP实验结果: 服务器端:
客户端:
一、实验目的 理解名字与IP地址的转换函数,实现主机名与IP地址之间的转换。学习和掌握Linux下的gethostbyname()和gethostbyaddr()函数基本原理和基本编程方法。 二、实验平台 ubuntu-8.04操作系统 三、实验内容 1、利用gethostbyname()函数编程实现名字解析,将主机名转换成相应IP地址。 2、利用gethostbyaddr()函数编程实现反向地址解析,将IP地址转换成主机名,查询指定IP地址对应的主机域名地址。 四、实验原理 现在的网络都是使用名字来访问服务器的,而不是使用IP地址来访问。那它们是怎么转换的呢?答案就是利用名字与IP地址的转换函数实现的:gethostbyname和gethostbyaddr在主机名字与IP地址间进行转换。 1、gethostbyname()函数 找主机名最基本的函数gethostbyname(),该函数执行如果成功,它返回一个指向结构hostent的指针,该结构中包含了该主机的所有IPv4地址或IPv6地址;如果失败返回空指针。下面是定义: ------------------------------------------------------------------- # include <netdb.h> struct hostent * gethostbyname (const char *hostname); ------------------------------------------------------------------- |
参数hostname是主机的域名地址,函数将查询的结果作为参数返回。如果失败返回空指针;如果成功此参数返回的非空指针指向如下的hostent结构: ------------------------------------------------------------------- struct hostent { char * h_name; /*主机的正式名称*/ char * * h_aliases; /*主机的别名列表*/ int h_addrtype; /*主机地址类型*/ int h_length; /*主机地址长度*/ char * * h_addr_list; *主机IP地址的列表*/ }; # define h_addr h_addr_list[0] /*在列表中的第一个地址*/ ------------------------------------------------------------------- | |
2、gethostbyaddr()函数 gethostbyaddr()函数的作用是可以查询指定的IP地址对应的主机域名地址。函数的形式如下: ------------------------------------------------------------------- # include <netdb.h> struct hostent * gethostbyaddr (const char *addr, size_t len, int family); ------------------------------------------------------------------- |
返回:若为非空指针,则表示成功;若为空指针,则表示出错,同时设置h_errno。该函数同样返回一个指向结构hostent的指针。而在参数中,参数addr不是char *类型,而是一个真正指向含有IPv4或IPv6地址的结构in_addr或in6_addr的指针;len是此结构的大小,对于IPv4地址为4,对于IPv6地址为16;参数family为AF_INET或AF_INET6。 五、实验步骤 1、登陆进入ubuntu操作系统,新建一个文件,命名为gethostbyname.c,新建另一个文件,命名为gethostbyaddr.c。 2、在gethostbyname.c和gethostbyaddr.c中编写相应代码并保存。 3、在“终端”(“Applications”→“附件”→“终端”)中执行命令进入gethostbyname.c和gethostbyaddr.c所在目录。(pwd命令可以显示当前所在目录;ls命令可以显示当前目录下的文件和文件夹信息;cd..命令可以进入上一级目录;cd 目录名 命令可以进入当前所示的某个目录。) 4、执行命令gcc –o gethostbyname gethostbyname.c生成可执行文件gethostbyname。 5、执行命令./gethostbyname host_name。(注意:此处host_name代表主机名,利用命令hostname可以查看本机的主机名) 6、观察并分析程序运行结果。 7、执行命令gcc –o gethostbyaddr gethostbyaddr.c生成可执行文件gethostbyaddr。 8、执行命令./gethostbyname 127.0.0.1,观察结果。 9、认真分析源代码,体会gethostbyname()和gethostbyaddr()函数的应用。 六、参考程序 1、gethostbyname.c内容如下: - #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <netdb.h>
-
- main(int argc, const char **argv)
- {
- ulong addr;
- struct hostent*hp;
- char **p;
- if (argc !=2) {
- (void)printf("usage: %s host_name\n", argv[0]);
- exit(1);
- }
- hp =gethostbyname(argv[1]);
- if (hp ==NULL) {
- (void)printf("host information for %s not found\n", argv[1]);
- exit(2);
- }
- for (p =hp->h_addr_list; *p != 0; p++) {
- structin_addr in;
- char**q;
- (void)memcpy(&in.s_addr, *p, sizeof(in.s_addr));
- (void)printf("%s\t%s", inet_ntoa(in), hp->h_name);
- for(q = hp->h_aliases; *q != 0; q++)
- (void) printf(" %s", *q);
- (void)putchar('\n');
- }
- exit (0);
- }
-
2、gethostbyaddr.c内容如下: - #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <netdb.h>
-
- main(int argc, const char **argv)
- {
- ulong addr;
- structhostent *hp;
- char **p;
- if (argc !=2) {
- (void)printf("usage: %s IP-address\n", argv[0]);
- exit(1);
- }
- if((int)(addr = inet_addr(argv[1])) == -1) {
- (void)printf("IP-address must be of the form a.b.c.d\n");
- exit(2);
- }
- hp =gethostbyaddr((char *)&addr, sizeof (addr), AF_INET);
- if (hp ==NULL) {
- (void)printf("host information for %s not found\n", argv[1]);
- exit(3);
- }
- for (p =hp->h_addr_list; *p != 0; p++) {
- structin_addr in;
- char**q;
- (void)memcpy(&in.s_addr, *p, sizeof (in.s_addr));
- (void)printf("%s\t%s", inet_ntoa(in), hp->h_name);
- for(q = hp->h_aliases; *q != 0; q++)
- (void) printf(" %s", *q);
- (void)putchar('\n');
- }
- exit (0);
- }
-
摘要: 一、实验目的理解进程的创建和终止方法;熟悉父进程与子进程对描述符的操作过程;学会编写基本的多进程并发服务器程序和客户程序。二、实验平台ubuntu-8.04操作系统三、实验内容编写多进程并发服务器程序和客户程序,具体功能如下:1、服务器等待接收客户的连接请求,一旦连接成功则显示客户地址,接着接收客户端的名称并显示;然后接收来自该客户的字符串,每当收到一个字符串时,显示该字符串,并将字符串按照恺撒密... 阅读全文
一个seclect的封装
uint32 SocketWait(TSocket *s,bool rd,bool wr,uint32 timems) { fd_set rfds,wfds; #ifdef _WIN32 TIMEVAL tv; #else struct timeval tv; #endif /* _WIN32 */ FD_ZERO(&rfds); FD_ZERO(&wfds);
if (rd) //TRUE FD_SET(*s,&rfds); //添加要测试的描述字
if (wr) //FALSE FD_SET(*s,&wfds);
tv.tv_sec=timems/1000; //second tv.tv_usec=timems%1000; //ms
for (;;) //如果errno==EINTR,反复测试缓冲区的可读性 { switch(select((*s)+1,&rfds,&wfds,NULL, (timems==TIME_INFINITE?NULL:&tv))) //测试在规定的时间内套接口接收缓冲区中是否有数据可读 { //0--超时,-1--出错 case 0: /* time out */ return 0; case (-1): /* socket error */ if (SocketError()==EINTR) break; return 0; //有错但不是EINTR default: if (FD_ISSET(*s,&rfds)) //如果s是fds中的一员返回非0,否则返回0 return 1; if (FD_ISSET(*s,&wfds)) return 2; return 0; }; }
}
此命令用于为特定软件包打补丁,他使用diff命令对源文件进行操作。 基本命令语法: patch [-R] {-p(n)} [--dry-run] < patch_file_name p:为path的缩写。 n:指将patch文件中的path第n条’/’及其左边部分取消。 -R:卸载patch包。 --dry-run:尝试patch软件,并不真正修改软件。 使用实例: /home/sense/patch-2.6.19.1 ============================================================= diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index d12fb97..c8f96cf 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -333,7 +333,7 @@ acpi_parse_ioapic(acpi_table_entry_heade /* * Parse Interrupt Source Override for the ACPI SCI */ -static void acpi_sci_ioapic_setup(u32 bus_irq, u32 gsi, u16 polarity, u16 trigger) +static void acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) ============================================================= 此patch文件的path=a/arch/i386/kernel/acpi [sense@ssn src]$ pwd /usr/src [sense@ssn src]$ tree . `-- a `-- arch `-- i386 `-- kernel `-- acpi 和a/同目录时: [sense@ssn src]$ pwd /usr/src [sense@ssn src]$ patch -p0 < /home/sense/patch-2.6.19.1 安装补丁 [sense@ssn src]$ patch -p0 -R < /home/sense/patch-2.6.19.1 卸载补丁 和a/arch/同目录时: [sense@ssn src]$ pwd /usr/src/a/ [sense@ssn src]$ patch -p1 < /home/sense/patch-2.6.19.1 安装补丁 [sense@ssn src]$ patch -p1 -R < /home/sense/patch-2.6.19.1 卸载补丁 和a/arch/i386/同目录时: [sense@ssn src]$ pwd /usr/src/a/arch/ [sense@ssn src]$ patch -p2 < /home/sense/patch-2.6.19.1 安装补丁 [sense@ssn src]$ patch -p2 -R < /home/sense/patch-2.6.19.1 卸载补丁
_command void testslickc() { say("testslickc");
int ii = pos("ab", "zzzab"); say(ii); ii =pos("aa", "aazzzaa"); say(ii); ii = pos("ba", "aazzza"); say(ii);
//ii 为 0 ; ii = pos("Aa", "aazzza"); say(ii); //"I" "忽略大小写" ii = pos("Aa", "aazzza", 1,"I"); say(ii);
//"I " "忽略大小写" "&" "使用通配符" //使用通配符和忽略大小写 ii = pos("A*a", "aazzza", 1,"I&"); say(ii);
}
http://www.leetcode.com/2010/10/implement-strstr-to-find-substring-in.html Rabin-Karp algorithm, KMP algorithm, and the Boyer-Moore algorithm
|