帐前卒专栏

code, software architect, articles and novels.
代码,软件架构,博客和小说

计算机数据存储有两种字节优先顺序:高位字节优先和低位字节优先。Internet上数据以高位字节优先顺序在网络上传输,所以对于在内部是以低位字节优先方式存储数
据的机器,在Internet上传输数据时就需要进行转换。
我们要讨论的第一个结构类型是:struct sockaddr,该类型是用来保存socket信息的:
struct sockaddr {
unsigned short sa_family; /* 地址族, AF_xxx /
char sa_data[14]; /
14 字节的协议地址 / };
sa_family一般为AF_INET;sa_data则包含该socket的IP地址和端口号。
另外还有一种结构类型:
struct sockaddr_in {
short int sin_family; /
地址族 /
unsigned short int sin_port; /
端口号 /
struct in_addr sin_addr; /
IP地址 /
unsigned char sin_zero[8]; /
填充0 以保持与struct sockaddr同样大小 */
};
这个结构使用更为方便。sin_zero(它用来将sockaddr_in结构填充到与struct
sockaddr同样的长度)应该用bzero()或memset()函数将其置为零。指向sockaddr_in
的指针和指向sockaddr的指针可以相互转换,这意味着如果一个函数所需参数类型是sockaddr时,你可以在函数调用的时候将一个指向
sockaddr_in的指针转换为指向sockaddr的指针;或者相反。sin_family通常被赋AF_INET;sin_port和
sin_addr应该转换成为网络字节优先顺序;而sin_addr则不需要转换。
我们下面讨论几个字节顺序转换函数:
htons()–“Host to Network Short” ; htonl()–“Host to Network Long”
ntohs()–“Network to Host Short” ; ntohl()–“Network to Host Long”
在这里, h表示"host" ,n表示"network",s 表示"short",l表示 “long”。
打开socket 描述符、建立绑定并建立连接
socket函数原型为:
int socket(int domain, int type, int protocol);
domain参数指定socket的类型:SOCK_STREAM
或SOCK_DGRAM;protocol通常赋值"0"。Socket()调用返回一个整型socket描述符,你可以在后面的调用使用它。
一旦通过socket调用返回一个socket描述符,你应该将该socket与你本机上的一个端口相关联(往往当你在设计服务器端程序时需要调用该函数。随后你就可
以在该端口监听服务请求;而客户端一般无须调用该函数)。 Bind函数原型为:
int bind(int sockfd,struct sockaddr my_addr, int addrlen);
Sockfd是一个socket描述符,my_addr是一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针;addrlen常被设置为size
of(struct sockaddr)。
最后,对于bind 函数要说明的一点是,你可以用下面的赋值实现自动获得本机IP地址和随机获取一个没有被占用的端口号:
my_addr.sin_port = 0; /
系统随机选择一个未被使用的端口号 /
my_addr.sin_addr.s_addr = INADDR_ANY; /
填入本机IP地址 */
通过将my_addr.sin_port置为0,函数会自动为你选择一个未占用的端口来使用。同样,通过将 my_addr.sin_addr.s_addr置为IN
ADDR_ANY,系统会自动填入本机IP地址。Bind()函数在成功被调用时返回0;遇到错误时返回"-1"并将errno置为相应的错误号。另外要注意的是,当
调用函数时,一般不要将端口号置为小于1024的值,因为1~1024是保留端口号,你可以使用大于1024中任何一个没有被占用的端口号。
Connect()函数用来与远端服务器建立一个TCP连接,其函数原型为:
int connect(int sockfd, struct sockaddr serv_addr, int addrlen);
Sockfd是目的服务器的sockt描述符;serv_addr是包含目的机IP地址和端口号的指针。遇到错误时返回-1,并且errno中包含相应的错误码。进行
客户端程序设计无须调用bind(),因为这种情况下只需知道目的机器的IP地址,而客户通过哪个端口与服务器建立连接并不需要关心,内核会自动选择一个未被占用的端
口供客户端来使用。
Listen()——监听是否有服务请求
在服务器端程序中,当socket与某一端口捆绑以后,就需要监听该端口,以便对到达的服务请求加以处理。
int listen(int sockfd, int backlog);
Sockfd是Socket系统调用返回的socket 描述符;backlog指定在请求队列中允许的最大请求数,进入的连接请求将在队列中等待accept()它
们(参考下文)。Backlog对队列中等待服务的请求的数目进行了限制,大多数系统缺省值为20。当listen遇到错误时返回-1,errno被置为相应的错误码

故服务器端程序通常按下列顺序进行函数调用:
socket(); bind(); listen(); /
accept() goes here */
accept()——连接端口的服务请求。
当某个客户端试图与服务器监听的端口连接时,该连接请求将排队等待服务器accept()它。通过调用accept()函数为其建立一个连接,
accept()函数将返回一个新的socket描述符,来供这个新连接来使用。而服务器可以继续在以前的那个
socket上监听,同时可以在新的socket描述符上进行数据send()(发送)和recv()(接收)操作:
int accept(int sockfd, void *addr, int *addrlen);
sockfd是被监听的socket描述符,addr通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息(某台主机从某个
端口发出该请求);addrten通常为一个指向值为sizeof(struct sockaddr_in)的整型指针变量。错误发生时返回一个-
1并且设置相应的errno值。
Send()和recv()——数据传输
这两个函数是用于面向连接的socket上进行数据传输。
Send()函数原型为:
int send(int sockfd, const void *msg, int len, int flags);
Sockfd是你想用来传输数据的socket描述符,msg是一个指向要发送数据的指针。
Len是以字节为单位的数据的长度。flags一般情况下置为0(关于该参数的用法可参照man手册)。
char *msg = “Beej was here!”; int len, bytes_sent; … …
len = strlen(msg); bytes_sent = send(sockfd, msg,len,0); … …
Send()函数返回实际上发送出的字节数,可能会少于你希望发送的数据。所以需要对send()的返回值进行测量。当send()返回值与len不匹配时,应该对这
种情况进行处理。
recv()函数原型为:
int recv(int sockfd,void *buf,int len,unsigned int flags);
Sockfd是接受数据的socket描述符;buf
是存放接收数据的缓冲区;len是缓冲的长度。Flags也被置为0。Recv()返回实际上接收的字节数,或当出现错误时,返回-1并置相应的errno值。
Sendto()和recvfrom()——利用数据报方式进行数据传输
在无连接的数据报socket方式下,由于本地socket并没有与远端机器建立连接,所以在发送数据时应指明目的地址,sendto()函数原型为:
int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct
sockaddr *to, int tolen);
该函数比send()函数多了两个参数,to表示目地机的IP地址和端口号信息,而tolen常常被赋值为sizeof (struct
sockaddr)。Sendto 函数也返回实际发送的数据字节长度或在出现发送错误时返回-1。
Recvfrom()函数原型为:
int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr
*from,int *fromlen);
from是一个struct sockaddr类型的变量,该变量保存源机的IP地址及端口号。fromlen常置为sizeof (struct sockaddr
)。当recvfrom()返回时,fromlen包含实际存入from中的数据字节数。Recvfrom()函数返回接收到的字节数或当出现错误时返回-1,并置相
应的errno。
应注意的一点是,当你对于数据报socket调用了connect()函数时,你也可以利用 send()和recv()进行数据传输,但该socket仍然是数据报
socket,并且利用传输层的UDP服务。但在发送或接收数据报时,内核会自动为之加上目地和源地址信息。
Close()和shutdown()——结束数据传输
当所有的数据操作结束以后,你可以调用close()函数来释放该socket,从而停止在该socket上的任何数据操作:close(sockfd);
你也可以调用shutdown()函数来关闭该socket。该函数允许你只停止在某个方向上的数据传输,而一个方向上的数据传输继续进行。如你可以关闭某socke
t的写操作而允许继续在该socket上接受数据,直至读入所有数据。
int shutdown(int sockfd,int how);
Sockfd的含义是显而易见的,而参数 how可以设为下列值:
·0-------不允许继续接收数据
·1-------不允许继续发送数据
·2-------不允许继续发送和接收数据,均为允许则调用close ()
shutdown在操作成功时返回0,在出现错误时返回-1(并置相应errno)。
DNS——域名服务相关函数
由于IP地址难以记忆和读写,所以为了读写记忆方便,人们常常用域名来表示主机,这就需要进行域名和IP地址的转换。函数gethostbyname()就是完成这种
转换的,函数原型为:
struct hostent *gethostbyname(const char *name);
函数返回一种名为hosten的结构类型,它的定义如下:
struct hostent {
char h_name; / 主机的官方域名 */
char *h_aliases; / 一个以NULL结尾的主机别名数组 /
int h_addrtype; /
返回的地址类型,在Internet环境下为AF-INET */
int h_length; /*地址的字节长度 */
char h_addr_list; / 一个以0结尾的数组,包含该主机的所有地址/
};
#define h_addr h_addr_list[0] /在h-addr-list中的第一个地址/

转至 sucn .com

研究好多天了,也试过好多办法了,总结出目前发现最好的方法:
先说一下基本的东西:
<%@ codepage=936%>简体中文
<%@ codepage=950%>繁体中文
<%@ codepage=65001%>UTF-8
codepage指定了IIS按什么编码读取传递过来的串串(表单提交,地址栏传递等)。

出乱码的原因也就是网站要整合的时候模块编码不一样引起的。
就像我的博客一样,整合的时候都会出这个问题,因为BLOG是Utf-8的,
近来很多网友都在为这个问题咨询,我尝试了很多种方法。
最方便的方法如下:
不要转换任何模块网页的编码该utf-8的还是utf-8,该Gb22312的还是Gb2312
在Utf-8模块的包文件(如conn.asp,但是要注意conn.asp必须是在第一行调用)最前面加上
<%@LANGUAGE=“VBSCRIPT” CODEPAGE=“65001”%>
<%Session.CodePage=65001%>
在GB2312模块的包文件最前面加上
<%@LANGUAGE=“VBSCRIPT” CODEPAGE=“936”%>
<%Session.CodePage=936%>
其他编码的类推。再出问题,我也帮你了了,我现在是都没问题了^^

JSP中文问题

一、JSP页面显示乱码二、表单提交中文时出现乱码三、数据库连
大家在JSP的开发过程中,经常出现中文乱码的问题,可能一至困扰着您,我现在把我在JSP开发中遇到的中文乱码的问题及解决办法写出来供大家参考。

一、JSP页面显示乱码
下面的显示页面(display.jsp)就出现乱码:

JSP的中文处理 <% out.print("JSP的中文处理"); %> 对不同的WEB服务器和不同的JDK版本,处理结果就不一样。原因:服务器使用的编码方式不同和浏览器对不同的字符显示结果不同而导致的。解决办法:在JSP页面中指 定编码方式(gb2312),即在页面的第一行加上:<%@ page contentType="text/html; charset=gb2312"%>,就可以消除乱码了。完整页面如下: <%@ page contentType="text/html; charset=gb2312"%> JSP的中文处理 <% out.print("JSP的中文处理"); %>

二、表单提交中文时出现乱码
下面是一个提交页面(submit.jsp),代码如下:

JSP的中文处理
下面是处理页面(process.jsp)代码: <%@ page contentType="text/html; charset=gb2312"%> JSP的中文处理 <%=request.getParameter("name")%> 如果submit.jsp提交英文字符能正确显示,如果提交中文时就会出现乱码。原因:浏览器默认使用UTF-8编码方式来发送请求,而UTF-8和GB2312编码 方式表示字符时不一样,这样就出现了不能识别字符。解决办法:通过request.setCharacterEncoding("gb2312")对请求进行统一编码 ,就实现了中文的正常显示。修改后的process.jsp代码如下: <%@ page contentType="text/html; charset=gb2312"%> <% request.seCharacterEncoding("gb2312"); %> JSP的中文处理 <%=request.getParameter("name")%>

三、数据库连接出现乱码
只要涉及中文的地方全部是乱码,解决办法:在数据库的数据库URL中加上useUnicode=true&characterEncoding=GBK就OK了。

四、数据库的显示乱码
在mysql4.1.0中,varchar类型,text类型就会出现中文乱码,对于varchar类型把它设为binary属性就可以解决中文问题,对于text类
型就要用一个编码转换类来处理,实现如下:
public class Convert {
/** 把ISO-8859-1码转换成GB2312
*/
public static String ISOtoGB(String iso){
String gb;
try{
if(iso.equals(“”) || iso == null){
return “”;
}
else{
iso = iso.trim();
gb = new String(iso.getBytes(“ISO-8859-1”),“GB2312”);
return gb;
}
}
catch(Exception e){
System.err.print(“编码转换错误:”+e.getMessage());
return “”;
}
}
}
把它编译成class,就可以调用Convert类的静态方法ISOtoGB()来转换编码。

没有想到自己竟然过了微软实习生的笔试和面试。 出乎过去的想像。本来是想不为学院丢脸就ok了。现在想想真的没有给学院丢脸。

上午进行的笔试,Tim Chen来的太晚了,本来说10点,结果快10点半才来。这半个小时里和老边闲聊了一阵。然后Tim就来了。先交了简历,然后自己简短的介绍
了下自己。自己写的简历最短,自己的介绍似乎也是最短的。说自己兴趣爱好的时候,我说自己喜欢写blog。Tim chen开玩笑的说:作家。我其实心里想,自己喜欢
看着blog的计数器慢慢增长。然后Tim让我们每人写篇英语短文介绍自己上午干了些什么。限时7分钟。具体用了多长时间我也保护太清楚,反正记得自己写了半页纸。然
后是最经典的atoi()函数编写,不过要写出测试用例。看来Tim真的是要招测试方面的人。限时大概15分钟。自我感觉良好,毕竟之前看过类似的题。最后一题:写一
个汉英字典类。自己想了想用两个类实现。一个类是字典,另外一个是单词。还剩下最后2分钟的时候,突然想起他要用一个类。于是马上改过。写了些数据成员,然后加了增删
查改和构造析构6个方法。还剩10秒。心里不想写了。算了,我反正想不起更多的方法了。

下午吃饱喝足想睡觉,可迟迟睡不着。Tim说下午打电话通知来面试。睡不着就起来洗个澡。结果还是没有电话来。心有些凉,感觉也不会录自己了,还不如去看看信息安全。
正想着,浩哥就打来电话找我面试。

下午面试自我感觉还算良好。没有说错什么,只是说了些自己的缺点和不足。并且很高兴的告诉tim今天学院推荐的五个人其中有4个曾是自己的组员。然后我们俩就聊起来X
P方法。后来Tim问是否有意向去微软。感觉怪怪的。为什么不说你被录取了。想不通。。。。最后Tim主动与我握手。感觉有些惭愧,没有主动和他握手。下次再见的时候
补上好了。
晚上有些兴奋,依然没有睡好觉。

由字符串转为int型…

int strToInt(const char * c)
{
if(c == NULL)
throw “NULL point…”;
int sum = 0;
int n = 10;
int flag = 1;
while(*c)
{
if(*c == ’ '||*c == ‘+’)
{
c++;
continue;
}
if(*c == ‘-’)
{
flag = -1;
c++;
continue;

}
sum *= n;
sum += c-‘0’;
c++;
}
return sum
flag;
}

sizeof()用于查看变量 所占的空间。例如:

sizeof(int) // 4

sizeof(float)// 4

sizeof(double)//8

sizeof(char) //1

char * p = new char[20];sizeof(p)//这里是p指针所占的空间故为4

char * p = “google”;sizeof(p);//这里是p指针指向字符串常量,但sizeof()的结果仍然为4

char *p [20];//这时sizeof()为80 = 20 × 4

char p[20];sizeof(p);//这里的结果为20 = 20 × 1

sizeof()使用了编译器生成的符号表的缘故。编译器的符号表类似于下面的形式,将所有的变量和其类型都记录在表中。

变量                  类型             大小

p                        char             10----------(数组)

a                        char              1

b                       double          8

d                       point              4

当要sizeof(变量)时,sizeof就会查取符号表。如果是单一类型的变量就会直接输出此类型变量的所占大小。并且也可以同时知道这个变量是否是数组。

但是Class类型稍稍有些不同,以下代码:

class A
{
public:
int a;
int b;
private:
int c;
protected:
char d;
double x;
};

sizeof(A)//24.为什么不是 3*4+1+8 = 21? 因为编译器要做优化,所以采用的是4Byte一体,也就符合我们常说的32位机的原理。也就是
机器的cpu可以同时处理32位二进制。所以地址线也做成了32位方便传输。编译器就将A优化为24Byte.但这只是对于32位机器有效。Vista等支持64位机
器。所以以后的VS2008等高级版本可能要将这个优化为可以被8B整除的字节数。

在字符表中,编译器大概会如此存储:类名  分隔符  变量名,这样即保证变量不会重名,又可以知道是那个类中的变量。

A::a      int         4

A::b      int         4

A::c       int         4

A::d      char      1

A::x      double   8

当调用sizeof(A)的时候,编译器会去寻找A类的所有变量,相加后如果不能被4整除,将变为最接近的4的倍数。

strlen()用于返回字符串的长度。但是不包括最后的’/0’

char * p = “google”; strlen(p);//结果为6

char * p = new char [20];
strlen(p)//???这里结果不能确定,原因是不知道何处有’/0’,strlen是查找到’/0’结束

strlen()函数的大概写法:

int strlen(const char * strSrc)
{
if(strSrc == NULL)
throw “NULL point…”;
int i = 0;
while(*strSrc++!=‘/0’)
i++;
return i;
}

不动者厚地,不息者高天。 无穷者日月,长在者山川。

松柏与龟鹤,其寿皆千年。

早出向朝市,暮已归下泉。形质及寿命,危脆若浮烟。

尧舜与周孔,古来称圣贤。借问今何在,一去亦不还。

我无不死药,万万随化迁。所未定知者,修短迟速间。

幸及身健日,当歌一尊前。何必待人劝,持此自为欢。

嗟嗟群物中,而人独不然。

要显示中文必须使用unsigned char型,如果使用char 就装不下了。

然后要明白一个unsigned char 其实只是装了一个中文字符的一半。打印的时候如果只打印一个unsigned
char有可能什么都看不到。所以逆转的时候要把两个unsigned char看成一个整体来交换。代码如下:

#include < iostream >
using namespace std;
int main( void )
{
unsigned char * string1 = new unsigned char [ 20 ];
unsigned char * b , * p;
b = p = string1;
while ( * p)
{

p ++ ;

}

p = p - 2 ;
while (p > b)
{
swap( * p, * b);
p ++ ;
b ++ ;
swap( * p, * b);
p = p - 3 ; // 转到下一个中文字符的第一个unsigned char
b ++ ;
}
cout << string1;
return 0 ;
}

其中的while(*p){p++;}p-=2;也可以用p = &string1[strlen(string1)-2]代替。。


char * Reverse( const char * str)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
kStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/
ContractedBlock.gif) … {

if (str == NULL)

throw " Null point " ;

int size = strlen(str);

if (size == 0 )

return “” ;


const char * p = str;

char * newStr = new char [size + 1 ];

char * temp = newStr;


while ( * p ++ );

p = p - 2 ; // 到达末尾的非’/0’字符

int i = 0 ;

while (p != str && i < size )
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {

unsigned char * x = (unsigned char * )p;

if ( * x > 0x7f )
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
rs/ContractedSubBlock.gif) … {

// DBCS

  • temp ++ = *-- p;
  • temp ++ = *++ p;

    p = p - 2 ;

    i += 2 ;
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
    lockEnd.gif) }

    else
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
    lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
    rs/ContractedSubBlock.gif) … {

    // SBCS
  • temp ++ = * p -- ;

    i ++ ;
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
    lockEnd.gif) }
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
    lockEnd.gif) }

    if (i < size)
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
    lockStart.gif) ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicato
    rs/ContractedSubBlock.gif) … {
  • temp ++ = * str;
    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubB
    lockEnd.gif) }
  • temp = ’ /0 ’ ;

    return newStr;

    ![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBloc
    kEnd.gif) }

同时发现一个CSDN插入代码的bug。当插入代码中出现‘/0’的时候就会截断。所以我只能用’//0’代替了。

当字符串中有DBCS双字节字符时,使用同时转换两个。当有SBCS单字节字符串时转换一个。

(但是有些DBCS字符是占用两个以上空间的。但是没有考虑)这只是个简单的转换。

Character values of type unsigned char have a range from 0 to 0xFF
hexadecimal. A signed char has range 0x80 to 0x7F. These ranges translate to 0
to 255 decimal, and –128 to +127 decimal, respectively. The /J compiler option
changes the default from signed to unsigned.

char 是无符号的
unsigned char 是无符号的,里面全是正数

两者都作为字符用的话是没有区别的,但当整数用时有区别:
char 整数范围为-128到127,
而unsigned char 整数范围为0到255

多数情况下,char ,signed char 、unsigned char 类型的数据具有相同的特性然而当你把一个单字节的数赋给一个大整型数域时,便会看到
它们在符号扩展上的差异。另一个区别表现在当把一个介于128和255之间的数赋给signed char
变量时编译器必须先进行数值转化,同样还会出现警告。若使用十六进制进行赋值使用unsigned char
要方便一些.根据编译器具体实现情况不同,char要么和signed char等同,要么和unsigned char等同.

unsigned char*跟char *是一样的。

功能:统计字符串里面的汉字的个数 (gb2312编码内码大于0xa0)

char szText[]= “12345你好”;

l= strlen(szText);
int sum=0;
for (int i=0; i< l; i++)
if (szText[i] > 0xa0)
sum++;
sum/=2;

这样你根本统计出到任何汉字,
因为char是有符号的,打最大就是127,超过就变成复数了。比如7f 是127,那么80就是-1了。
这时候你一定要写成
unsigned char szText[]= “12345你好”;

这期的是动漫专刊,感觉要办刊物就要办的活些。让其他的成员也办几期。这次是动漫专刊,也花了点点不少精力。不过我认为是至今为止办的最好的一期了。

下载地址:

http://ss.hnu.cn/newweb/students/yuankan/download/
_ 青春缘代码动漫专刊.rar _

同样贴到迅雷上即可。

0%