`
helloyesyes
  • 浏览: 1303945 次
  • 性别: Icon_minigender_2
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

Linux Socket学习(十八)--完

阅读更多

一个实际的网络工程

不论我们的头脑是否在由上一章的学习中清醒过来,现在我们需要休息一下了。在这一章我们并不讨论新的内容,而是用我们所学到的这些东西来实现一些有趣的事情。在学习了这么多的东西之后来一些有趣的东西是十分重要的。

在这一章,我们将会:

应用TCP/IP套接口从网上下载股票行情信息
应用UDP广播和我们的局域网内发布股票行情信息
使用UDP客户端程序来接收局域网广播的股票行情信息

问题描述

在提供解决方案之前进行问题描述是一个很好的习惯。所以,在这里我们要描述一下在这一章我们将会解决的问题。

我们有一个全职或是兼职的小公司。我们的办公室很小,所以免费得到一些行情信息是十分重要的。另外,我们需要关注我们的主机也网络提供商之间的网络拥塞,因为我们还需要为其他的事情准备网络带宽。同时,我们的公司职员也坚持得到最好的免费的行情信息。

解决行情服务问题

由问题描述我们可以很清楚的看出我们需要由行情提供者处得到一组行情信息。我们没有理由使得我们的公司员工使用单独的TCP/IP连接到同一个行情提供者来获得同样的信息。这会耗尽宝贵的网络带宽。从免费的行情提供者的角度来看,这也是不必要的。

一个本地服务器程序可以持续的为大家获取更新的股票市场行情信息。然后,这个信息可以播报到网络中的所有参与者。这就是我们在这一章将会提供的解决方案。这个程序也会使得我们回忆复习流式套接口与数据报套接口。

得到股票市场行情

我们要使用的市场行情信息的数据源为finance.yahoo.com。在这一部分,我们将会了解程序如何由finance.yahoo.com获取行情信息。

为 了确定如何猎取市场行情,我们可以使用网络浏览器来访问htt://finance.yahoo.com。此时,网站会提供给我们一个页面,允许我们输入 符号并且点击Get Quotes按钮。输入RHAT并且按下按钮会将我们引入另一个页面,在这里我们可以得到关于Red Hat Inc的详细信息。在行情信息的底部,我们可以看到一个名为Download Spreadsheet Format的链接。这就是金矿所在。

在这里,我们有三个选择:

将鼠标移动该链接上,并且注意在状态行所显示的URL信息
从 菜单中选择View->Page Source。查看整个HTML代码,找到如下的部分:<a href="/d/ quotes.csv?s=RHAT&f=sl1d1t1c1ohgv&e=.csv">Download Spreadsheet Format</a>

在Netscape中获取这个信息的最好方法就是在链接上点击右键。从弹出菜单中选择Copy Link Location。这会将链接引用拷贝到剪切板中。然后,我们可以将这个信息粘贴到文件中。

从这个信息,我们可以得到我们需要的全部分内容。我们可以使用telnet来试验这些内容:

$ telnet finance.yahoo.com 80
Trying 204.71.201.75 . . .
Connected to finance.yahoo.com.
Escape character is '^]'.
GET /d/quotes.csv?s=RHAT&f=sl1d1t1c1ohgv&e=.csv
"RHAT",168.9375,"11/24/1999","4:00PM",0,147.5625,175.5,145.6875,3061700
Connection closed by foreign host.
$

在我们连接之后执行GET命令,同时指定一个奇怪的路径名并按下回车键。如果命令执行成功,我们就会得到一行扩展数据。将RHAT替换为另一个代码我们就会得到不同的数据。

如 果我们没有这样好的运气,那么我们需要检查一下我们的拼写。精确在这里是非常重要的。如果可能可以使用剪切粘贴的操作。如果仍不起作用,那么我们需要查看 一下finance.yahoo.com现在是如何工作的。由前面我们所指出的步骤框架我们可以发现所需要的新的主机名与路径名。

下面是行情获取步骤的小结:

1 在80商品连接到finance.yahoo.com
2 使用所显示的路径名来执行GET请求
3 一行表格格式数据会作为响应返回套接口
4 关闭套接口

这就是所有的步骤。当我们检测后面所列出的代码时我们要记住这些步骤。

后面的章节内容会演示并描述组成服务器与客户端程序所需要的各个模块。然而由于空间的原因,我们在这里并不能列出全部的代码。

下表列出了我们所需要的源码文件。其中一些有趣的部分会在这一章进行相关的描述。

源文件 描述
Makefile 工程make文件
bcast.c 实现执行向局域网广播的函数
connect.c 实现执行连接到远程行情服务器的函数
csvparse.c 分析返回的行情数据
gettick.c 从远程网行情服务器得到行情信息
load.c 由文件tickers.rc装入股票市场代码
misc.c 一些小函数
mkaddr.c 网络地址函数
mkwatch.c 市场监测客户端程序。这个程序会接收本地广播信息并显示
msgf.c 实现本地行情服务器的模块
quotes.h 所有源模块所用的通常头文件
tickers.rc 股票代码文件

检测行情服务器程序

我们将要开始检测源码模块为qserve.c源码模块。这个模块为行情服务器本身形成主程序。他负责获取股票市场行情并且向局域网进行广播。下面列出了qserve.c的源代码:
/*
* qserve.c:
*
* Stock Quote Connentrator Program:
*/
#include "quotes.h"

static char *command = NULL;

/*
* Remote Quote Server Address */
static char *cmdopt_a = DFLT_SERVER;

/*
* Quote Re-Broadcase Address
*/
static char *cmdopt_b = DFLT_BCASE;

/*
* Ticker Table:
*/
static TickReq tickers[MAX_TICKERS];
static int ntick=0;

/*
* Return server usage information:
*/
static void usage(void)
{
printf("Usage: %s [-h] [-a address:port]\n"
"where:\n"
"\t-h\t\tRequests usage info.\n"
"\t-a address:port\tSpecify "
"the server\n"
"\t\t\taddress and port number.\n"
"\t-b bcastport \tSpecify "
"the broadcase\n"
"\t\t\taddress and port number.\n",
command);
}

/*
* Server main program:
*/
int main(int argc,char **argv)
{
int rc=0; /* Return code */
int optch; /* Option char */
int z; /* Status code */
int x; /* Index */
int s; /* Broadcast socket */
time_t tn=0; /* Time Next */
time_t zzz; /* Sleep Time */
time_t td; /* Time & Date */
struct sockaddr_in bc_addr; /* bc addr */
socklen_t bc_len; /* bc addr len */
const int True = TRUE; /* const TRUE */
static char cmdopts[]="ha:b:";

/*
* Process command line options:
*/
command = Basename(argv[0]);

while((optch = getopt(argc,argv,cmdopts)) != -1)
switch(optch)
{
case 'h': /* -h for help */
usage();
return rc;

case 'a': /* -a quote_server */
cmdopt_a = optarg;
break;

case 'b': /* -b broadcast_addr */
cmdopt_b = optarg;
break;

default:
/* Option error */
rc=1;
}

/* check for option errors: */
if(rc)
{
usage();
return rc;
}

/*
* Form the broadcast server address:
*/
bc_len = sizeof bc_addr; /* Max len */
z = mkaddr(
&bc_addr, /* Returned addr */
&bc_len, /* Returned len */
cmdopt_b, /* Input address */
"udp"); /* UDP protocol */

if(z==-1)
{
msgf('e',"%s: -b %s",
strerror(errno),
cmdopt_b);
return 1;
}

/*
* Create a UDP socket to use:
*/
s = socket(PF_INET,SOCK_DGRAM,0);
if(s==-1)
{
msgf('e',"%s: socket(PF_INET,"
"SOCK_DGRAM,0)",
strerror(errno));
return 1;
}

/*
* Allow broadcasts on socket s:
*/
z = setsockopt(s,
SOL_SOCKET,
SO_BROADCAST,
&True,
sizeof True);
if(z==-1)
{
msgf('e',"%s: setsockopt(SO_BROADCAST)",
strerror(errno));
return 1;
}

/*
* Load tickers form tickers.rc:
*/
if(load(&tickers[0],&ntick,MAX_TICKERS))
goto errxit;

/*
* Now monitor the remote quote server:
*/
for(;;)
{
tn = 0; /* Refresh tn */
time(&td); /* current time */

/*
* Loop for all tickers:
*/
for(x=0;x<ntick;++x)
{
/*
* Skip tickers that are either
* unknown,or are producing parse
* errors in the returned data:
*/
if(tickers[x].flags & FLG_UNKNOWN
|| tickers[x].flags & FLG_ERROR)
continue; /* Ignore this */

/*
* Pick up the earliest "next" time:
*/
if(!tn
|| tickers[x].next_samp < tn)
tn = tickers[x].next_samp;

/*
* if the current time is > than
* the "next" time,it is time to
* fetch an update for this ticker:
*/
if(td>=tickers[x].next_samp)
{
/*
* Get Quote Update:
*/
z = get_tickinfo(
&tickers[x],cmdopt_a);

/*
* comute time for the next
* update for this ticker:
*/
time(&tickers[x].next_samp);
tickers[x].next_samp += tm;

/*
* if the uote fetch was OK,
* then broadcast its info:
*/
if(!z)
broadcast(s,&tickers[x],
(struct sockaddr *)&bc_addr,
bc_len);
}
}

/*
* Here the interval between updates is
* progressively increased to 5 minutes
* max.This provides a lot of initial
* acction for demonstration puoposes,
* without taxing the friendly quote
* providers if this program is run all
* day.Abuse will only force the kind
* providers to change things to break
* the operation of this program!
*/
if(tm < (time_t)5*60)
tm += 5; /* progressively increase */

/*
* compute how long we need to snooze.
* the time to the next event is
* computed-sleep(3) is called if
* necessary:
*/
if(!tn)
tn = td + tm;
if(tn>=td)
if((zzz = tn-td))
sleep(zzz);
}

return rc;

/*
* Error Exit:
*/
errxit:
return rc=2;
}

通过get_tickinfo()函数获取行情信息

这一部分将会检测gettkick.c源码模块,从而我们可以看到如何通过C代码来获取行情信息。在显示这个模块之前,我们需要检测一些会用到的引用结构。下面列出了在这个工程中一些源码模块会用到的quotes.h头文件:
/*
* quotes.h:
*
* Project header file:
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <getopt.h>
#include <memory.h>
#include <stdarg.h>
#include <math.h>
#include <syslog.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>

/*
* Default Quote Server:
*/
#define DFLT_SERVER "finance.yahoo.com:80"

/*
* Default Broadcast Address:
*/
#define DFLT_BCAST "127.255.255.255:977"

/*
* *.CSV Parsing Parameter:
*/
typedef struct
{
char type; /* 'S' or 'D' */
void *parm; /* Ptr to parameter */
} Parm;

/*
* Timeout on Quote Fetch:
*/
#define TIMEOUT_SECS 10

/*
* Ticker load file:
*/
#define TICKPATH "tickers.rc"

/*
* Maximum number of tickers:
*/
#define MAX_TICKERS 256

/*
* Ticker length:
*/
#define TICKLEN 8

/*
* Date Length:
*/
#define DTLEN 10

/*
* Time field length:
*/
#define TMLEN 7

/*
* Define TRUE & FALSE if not defined:
*/
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

/*
* Ticker Request Structure:
*/
typedef struct
{
char ticker[TICKLEN+1]; /* Symbol */
double last_trade; /* Last Price */
char *date; /* Date */
char *time; /* Time of Last Trade */
double change; /* +/- change */
double open_price; /* Opening Price */
double high; /* High Price */
double low; /* Low Price */
double volume; /* Volume of Trades */
int flags; /* Server flags */
time_t next_samp; /* Time of next evt */

} TickReq;

/*
* Ticker Flags:
*/
/* Ticker unknown */
#define FLG_UNKNOWN 1

/* Data format error */
#define FLG_ERROR 2

/*
* External Function References:
*/
extern int load(TickReq *tick,int *pntick,int nmax);
extern int extract_parms(Parm *plist,short n,char *src);
extern void msgf(char type,const char *format,...);
extern int Connect(const char *addr);
extern int mkaddr(void *addr,
int *addrlen,
char *str_addr,
char *protocol);
extern char *Basename(char *cmd);
extern char *strtick(char *str);
extern int get_tickinfo(TickReq *req,char *addr);
extern void broadcast(
int s,TickReq *quote,struct sockaddr *bc_addr,
socklen_t bc_len);

有了头文件,现在我们就可以检测gettick.c源码模块了。
/*
* gettick.c
*
* Get ticker info from inet:
*/
#include "quotes.h"

/*
* f is set TRUE when a request
* for a stock quote has timed
* out.
*/
static int f = FALSE;

/*
* Catch SIGALRM and Timeout:
*/
static void sig_ALRM(int signo)
{
f = TRUE; /* Mark timeout */
}

/*
* Get ticker info:
*
* Returns:
* 0 success
* -1 failed
*
* errno:
* ETIME Timed out
* EBADMSG Failed data format
* other Network/system errors
*/
int get_tickinfo(TickReq *req,char *addr)
{
int z,er; /* Status,errno */
int s; /* Socket */
int n; /* Byte count */
char buf[256]; /* Receive buffer */
char *tkr=NULL; /* Extracted ticker */
struct sigaction
sa_new, /* New signal action */
sa_old; /* Saved signal action */
Parm parms[9]; /* Data parse table */

/*
* Initialize parsing parameters.This
* parameter list will need modification
* if yahoo or your quote provider uses
* a different format:
*/
parms[0].type = 'S'; /* String */
parms[0].parm = &tkr; /* Ticker name */
parms[1].type = 'D'; /* Double */
parms[1].parm = &req->last_trade;
parms[2].type = 'S';
parms[2].parm = &req->date;
parms[3].type = 'S';
parms[3].parm = &req->time;
parms[4].type = 'D';
parms[4].parm = &req->change;
parms[5].type = 'D';
parms[5].parm = &req->open_price;
parms[6].type = 'D';
parms[6].parm = &req->high;
parms[7].type = 'D';
parms[7].parm = &req->low;
parms[8].type = 'D';
parms[8].parm = &req->volume;

/*
* Initialize to cat SIGALRM:
*/
sa_new.sa_handler = sig_ALRM;
sigemptyset(&sa_new.sa_mask);
sa_new.sa_flags = 0;
sigaction(SIGALRM,&sa_new,&sa_old);

/*
* Connect to finance.yahoo.com:
*/
f = FALSE;
alarm(TIMEOUT_SECS);

s = Connect(addr);
if(s==-1)
goto errxit;

/*
* Send GET request:
* Note: This is subject to change
* if finance.yahoo.com changes,you
* will need to adjust this formatting.
*/
sprintf(buf,"GET /d/quotes.csv?"
"s=%s"
"&f=slldltlclohgv"
"&e=.csv\r\n",
req->ticker);
write(s,buf,strlen(buf));
shutdown(s,1);

/*
* Read response with a timeout:
*/
do
{
z = read(s,buf,sizeof buf);
} while(!if && z==-1 && errno==EINTR);

er = errno; /* Save error */
alarm(0); /* Diable timeout */
close(s); /* Close socket */

/* Restore the signal action */
sigaction(SIGALRM,&sa_old,NULL);

if(!f && z>0)
n=z; /* Read n bytes OK */
else
{
if(f) /* Timeout ? */
er = ETIME; /* Yes - timeout */

/*
* Report error to log:
*/
msgf('e',"%s: Get ticker '%s'",
strerror(er),
req->ticker);

errno = er; /* For caller */

return -1; /* Failed */
}

/*
* Remove CR,LF,or CRLF */
buf[strcspn(buf,"\r\n")]=0;

/*
* check for the unknown ticker case:
*/
if(strstr(buf,"N/A,N/A,N/A,N/A,N/A"))
{
msgf('e',"Unknown Ticker: '%s'",
req->ticker);
req->flags |= FLG_UNKNOWN;
errno = EBADMSG; /* For caller */
return -1; /* Failed */
}

/*
* Parse quote results:
*/
if((z=extract_parms(parms,9,buf))<0)
{
/*
* Report failed parse of data */
msgf('e',"Field # %d: '%s'",z,buf);
req->flags |= FLG_ERROR;
errno = EBADMSG; /* For caller */
return -1; /* Failed */

}

/*
* Capture the exact case for this ticker
*/
strncpy(req->ticker,tkr,TICKLEN)[TICKLEN]=0;

/*
* Update sample time in entry:
*/
return 0;

/*
* Error Exit:
*/
errxit:
alarm(0);
sigaction(SIGALRM,&sa_old,NULL);
return -1;
}

下面将会检测服务器程序所调用的broadcast()函数。

通过broadcast()广播

服务器通过调用名为broadcast()函数来与本地的网络客户端共享他的得到的信息。这个函数的代码如下:
/*
* bcast.c:
*
* Broadcast Ticker Updates
*/
#include "quotes.h"

void broadcast(
int s, /* Socket */
TickReq *quote, /* Quote */
struct sockaddr *bc_addr, /* addr */
socklen_t bc_len) /* addr len */
{
int z; /* status */
char buf[2048]; /* buffer */
char *cp = buf; /* buf. ptr */
int msglen; /* message length */

/*
* Format a datagram for broadcast:
*/
strcpy(buf,quote->ticker);
cp = buf + strlen(buf) +1;
sprintf(cp,"%E",quote->last_trade);
cp += strlen(cp)+1;
strcpy(cp,quote->date);
cp += strlen(cp)+1;
strcpy(cp,quote->time);
cp += strlen(cp)+1;
sprintf(cp,"%E",quote->change);
cp += strlen(cp)+1;
sprintf(cp,"%E",quote->open_price);
cp += strlen(cp)+1;
sprintf(cp,"%E",quote->high);
cp += strlen(cp)+1;
sprintf(cp,"%E",quote->low);
cp += strlen(cp)+1;
sprintf(cp,"%E",quote->volume);
cp += strlen(cp)+1;

msglen = cp-buf;

/*
* Broadcast the datagram:
*/
z = sendto(s,buf,msglen,0,bc_addr,bc_len);
if(z==-1)
msgf('e',"%s:sendto(2)",
strerror(errno));
}

检测客户端程序

客户端程序必须将其自身绑定到正在使用的广播地址,从而可以接收到广播市场行情信息。mktwatch.c模块代码如下:
/*
* mktwatch.c:
* Get datagram stock market
* quotes from central quotes
* server:
*/
#include "quotes.h"

/*
* -b option (broadcast) address:
*/
static char *cmdopt_b = DFLT_BCAST;

/*
* Dispaly command useage:
*/
static void usage(void)
{
puts("Usage:\tmktwatch [-b bcast]");
puts("where:");
puts("\t-b bcast\tBroadcast address");
}

/*
* Extract ticker information from
* broadcast datagram packet:
*/
static int extract(char *dgram,TickRe *tkr)
{
char *cp = dgram;
memset(tkr,0,sizeof *trk);
strncpy(tkr->ticker,dgram,TICKLEN)
[TICKLEN]=0;
cp += strlen(cp)+1;
if(sscanf(cp,"%lE",&tkr->last_trade) != 1)
return -1;
cp += strlen(cp)+1;
tkr->date = cp;
cp += strlen(cp)+1;
tkr->time = cp;
cp += strlen(cp)+1;
if(sscanf(cp,"%lE",&tkr->change)!=1)
return -1;
cp += strlen(cp)+1;
if(sscanf(cp,"%lE",&tkr->open_price) != 1)
return -1;
cp += strlen(cp)+1;
if(sscanf(cp,"%lE",&tkr->high) != 1)
return -1;
cp += strlen(cp)+1;
if(sscanf(cp,"%lE",&tkr->low) != 1)
return -1;
cp += strlen(cp)+1;
if(sscanf(cp,"%lE",&tkr->volume) != 1)
return -1;

return 0;
}

/*
* Market Watch Main Program:
*/
int main(int argc,char **argv)
{
int rc=0; /* command return code */
int optch; /* option character */
int z; /* status code */
int s; /* socket */
socklen_t bc_len; /* length */
struct sockaddr_in bc_addr; /* AF_INET */
socklen_t a_len; /* Address length */
struct sockaddr_in adr; /* AF_INET */
char dgram[2048]; /* Recv buffer */
const int True=TRUE; /* True const. */
TickReq tkr; /* Ticker Data */
const char cmdopts[] = "hb:";

/*
* Parse commnd line options:
*/
while((optch = getopt(argc,argv,cmdopt)) != -1)
switch(optch)
{
case 'h': /* -h (help) */
usage();
return rc;

case 'b': /* -b bc_addr */
cmdopt_b = optarg;
break;

default:
/* option error */
rc = 1;

}
if(rc)
{
usage(); /* option errors */
return rc;
}

/*
* Form broadcast address:
*/
bc_len = sizeof address;
z = mkaddr(
&bc_addr, /* returned addr */
&bc_len, /* returned len */
cmdopt_b, /* input address */
"udp"); /* udp protocol */
if(z==-1)
{
fprintf(stderr,
"%s: -b %s",
strerror(errno),
cmdopt_b);
return 1;
}

/*
* Create a udp socket to read from :
*/
s = socket(PF_INET,SOCK_STREAM,0);
if(s==-1)
{
fprintf(stderr,
"%s: socket(2)\n",
strerror(errno));
return 1;
}

/*
* Allow multiple listeners on this
* broadcast address:
*/
z = setsockopt(s,
SOL_SOCKET,
SO_REUSEADDR,
&True,
sizeof True);
if(z==-1)
{
fprintf(stderr,
"%s: setsockopt(SO_REUSEADDR)\n",
strerror(errno));
return 1;
}

/*
* Bind to the broadcast address:
*/
z = bind(s,
(struct sockaddr *)&bc_addr,bc_len);
if(z==-1)
{
fprintf(stderr,
"%s: bind(%s)\n",
strerror(errno),
cmdopt_b);
return 1;
}

/*
* Now listen for and process broadcaste
* stock quotes:
*/
for(;;)
{
/*
* wait for a broadcast message:
*/
a_len = sizeof adr; /* max addr len */
z = recvfrom(s, /* socket */
dgram, /* receiving buffer */
sizeof dgram, /* max rcv buf size */
0, /* flags: no options */
(struct sockaddr *)&adr, /* Addr */
&a_len); /* Addr len,in&out */
if(z<0)
{
fprintf(stderr,
"%s: recvfrom(2)\n",
strerror(errno));
break;
}

/*
* Extract and report quote:
*/
if(!extract(dgram,&tkr))
{
printf("%-*s %7.3f %s %7s %+7.3f %7.3f "
"%7.3f %7.3f %9.0f\n",
TICKLEN,
tkr.ticker,
tkr.last_trade,
tkr.date,
tkr.time,
tkr.change,
tkr.open_price,
tkr.high,
tkr.low,
tkr.volume);
fflush(stdout);
}
}

return 0;
}

编译并运行演示程序

要编译工程,我们可以使用Makefile文件,如下所示:
$ make
gcc -c -g -Wall -Wreturn-type -D_GNU_SOURCE qserve.c
gcc -c -g -Wall -Wreturn-type -D_GNU_SOURCE csvparse.c
gcc -c -g -Wall -Wreturn-type -D_GNU_SOURCE msgf.c
gcc -c -g -Wall -Wreturn-type -D_GNU_SOURCE load.c
gcc -c -g -Wall -Wreturn-type -D_GNU_SOURCE gettick.c
gcc -c -g -Wall -Wreturn-type -D_GNU_SOURCE bcast.c
gcc -c -g -Wall -Wreturn-type -D_GNU_SOURCE connect.c
gcc -c -g -Wall -Wreturn-type -D_GNU_SOURCE misc.c
gcc -c -g -Wall -Wreturn-type -D_GNU_SOURCE mkaddr.c
gcc -o qserve qserve.o csvparse.o msgf.o load.o gettick.o bcast.o connect.o
misc.o mkaddr.o
gcc -c -g -Wall -Wreturn-type -D_GNU_SOURCE mktwatch.c
gcc -o mktwatch mktwatch.o mkaddr.o
$

这会得到两个可执行文件:
qserve可执行文件,这是行情服务器程序
mktwatch可执行文件,这是广播监听客户端程序

http://www.quecorp.com/series/by_example/

PS:这本是一本在我的机子上放了很久的一本书,连在哪里下载得到的都不再记得了。直到一个偶然的机会试着看了一下,觉得一本很好的书,至少对于我来说是这样的,所以试着在这里翻译了一下,希望对大家会有一些小小的帮助。另外,最后的一个例子程序的源代码可以在上面的网址中得到,但是我自己访问是却打不开这个地址,不知道朋友们试了会是什么结果。

今天是元旦,2008的第一天,在这里萧易祝朋友们新年快乐~~

最后欢迎大家批评交流~~

分享到:
评论

相关推荐

    实战linux socket编程--示例源码.rar_C++ socket_linux 源码_socket 编程 linux_s

    在Linux系统中,Socket编程是实现网络通信的基础,它提供了进程间通过网络交换数据的接口。C++ Socket库是Linux下进行网络编程的常用工具,它允许开发者利用标准的C++语言来创建复杂的网络应用程序。本资源“实战...

    Linux-socket-TCP-ClientServer.zip_TCP socket_linux socket_linux

    在Linux系统中,TCP(Transmission Control Protocol)套接字是实现客户端与服务器间可靠通信的基础。本教程将探讨如何在...学习和掌握TCP socket编程对于开发网络应用程序至关重要,因为它是互联网通信的核心部分。

    项目使用Socket.IO-Client-Swift 绑定后台node服务器实现实时聊天功能.zip

    仿映客直播app(最新)原版礼物列表,直播弹幕,最新热门页面,原版动画登陆页,实现了oc项目使用Socket.IO-Client-Swift 绑定后台node服务器实现实时聊天功能 软件开发设计:应用软件开发、系统软件开发、移动应用...

    Linux Socket教程.zip

    最后,Linux Socket学习(十八)--完.txt可能是对整个教程的总结,回顾了重要的概念和技巧,并可能介绍了实际项目中的应用示例,如编写简单的TCP服务器或UDP客户端。 总的来说,这个Linux Socket教程全面地覆盖了...

    Linux Socket Programming by Example - II.pdf

    ### Linux Socket编程实战指南 #### 一、引言与历史背景 在《Linux Socket Programming by Example》这本书中,作者Warren W. Gay通过大量的实际案例深入浅出地讲解了Linux环境下Socket编程的基础知识和高级技巧。...

    socket-windows-and-linux.zip_Linux windows socket_linux c++ sock

    标题"socket-windows-and-linux.zip_Linux windows socket_linux c++ sock"表明了本主题涉及的是跨平台的Socket编程,主要关注Linux和Windows操作系统下,使用C++语言实现的Socket接口。描述提到"利用socket函数实现...

    实战Linux Socket 编程-示例源码

    在Linux系统中,Socket是一种进程间通信机制,它允许不同进程之间通过网络进行数据交换。本实战教程将通过具体的源码实例,帮助你深入理解Linux Socket编程的核心概念和技巧。 一、Socket基础知识 Socket是网络通信...

    linux socket programming-ibm

    通过学习和实践,开发者可以创建出能够跨网络进行通信的自定义应用,无论是简单的回显服务器和客户端,还是复杂的网络服务。同时,理解网络协议和套接字的工作原理,也有助于在更高层次的网络编程中选择合适的工具和...

    实战Linux Socket编程

    在IT领域,Linux Socket编程是网络通信的核心技术之一,它为开发者提供了在Linux操作系统上实现进程间通信(IPC)和网络通信的接口。本实战指南将深入探讨这一主题,帮助你掌握如何在Linux环境中构建高效的网络应用...

    LinuxSocket示例代码

    在IT行业中,Linux Socket是进行网络通信的重要工具,尤其对于系统和网络程序员来说,理解和掌握Linux Socket编程至关重要。本示例代码提供了客户端(client)和服务器端(server)的实现,帮助初学者深入理解如何在...

    Linux系统设计-Linux C++ socket网络编程-即时通信系统

    Linux系统在科学计算、数据分析和机器学习等领域也有广泛应用。许多知名的科学计算软件都在Linux上开发和运行,Linux系统在各个领域都有广泛的应用,其强大的功能和灵活性使得它成为许多产品和服务的基础架构。

    Linux C++ socket网络编程----------即时通信系统.zip

    操作系统:LInux、树莓派、安卓开发、微机操作系统、网络操作系统、分布式操作系统等。此外,还有嵌入式操作系统、智能操作系统等。 网络与通信:数据传输、信号处理、网络协议、网络与通信硬件、网络安全网络与通信...

    实战Linux socket编程Linux Socket Programming By Example

    《实战Linux Socket编程》是...总之,《实战Linux Socket编程》的配套源代码是一个宝贵的资源,它使学习者能够动手实践,从而更好地掌握网络编程的核心概念和技术,对于提升Linux系统下的网络编程能力具有重要意义。

    Linux Socket

    Linux Socket是Linux操作系统中用于进程间通信(IPC)的一种接口,它允许程序通过网络协议进行数据传输。在本文中,我们将深入探讨Linux ...通过IBM技术论坛的文章,你可以更深入地了解和学习Linux Socket的各种细节。

    Linux Socket Programming (Linux 套接字编程)

    ### Linux Socket Programming (Linux 套接字编程) #### 知识点概览: 1. **Socket编程基础** ...通过以上知识点的学习,读者可以深入了解Linux环境下的Socket编程,并能够掌握如何设计和实现网络通信程序。

    LINUX-socket源码

    本文将深入探讨在C语言中实现的Linux Socket服务器与客户端的源码,这是一份非常有价值的参考资料,对于学习网络编程和理解Socket工作原理具有重要意义。 首先,让我们了解Socket的基本概念。在Linux中,Socket是...

    tcp-socket-file-transfer.rar_tcp socket linux

    总的来说,TCP Socket在Linux环境下的文件传输涉及到网络编程的基本原理和Linux系统调用,是学习网络编程和系统编程的重要实践环节。通过理解和实践这些概念,开发者可以构建出高效、可靠的网络应用。

    HP-Socket文档

    HP-Socket 提供了大量的 Demo 示例如:PUSH 模型示例、PULL 模型示例、PACK 模型示例、性能测试示例以及其它编程语言示例,以便让使用者能方便快速地学习和使用 HP-Socket。 HP-Socket 的特点 * 高性能:HP-Socket...

    linux socket学习.pdf

    本篇文章将根据给定文件“linux socket学习.pdf”的内容进行展开,重点讨论 socket 的定义、如何创建 socket 以及 socket 与其他常见 I/O 操作的区别。 #### 二、理解 Socket ##### 2.1 定义 Socket Socket 可以...

    C语言SOCKET编程--超级完整.doc

    ### C语言SOCKET编程知识点详解 #### 一、Socket编程概览 - **定义与概念**: ...通过上述知识点的学习,读者能够掌握Socket编程的基础知识和技术要点,为进一步开发复杂的网络应用程序打下坚实的基础。

Global site tag (gtag.js) - Google Analytics