公司走形式主义,非要我们写个小项目当作培训,用以学习socket。虽然我还是菜鸟,但绝非刚刚接触socket,3年前我就在linux下写过p2p程序,呵呵。正好从头到尾的读一下《unix网络编程》,没事写写读书报告自娱自乐。
TCP客户端的helloworld
程序从《unix网络编程》中抄下来的,改了一点东西。
#include
#include //包含一些 socket函数的头文件
#include //包含sockaddr_in的头文件
#include
//包含一些类似inet_pton这样的转换函数的头文件
#include //一些类型的定义
int main(int argc, char ** argv)
{
if(argc !=
2){
std::cout<<"usage:
execname \n";
exit(1);
}
//创建一个socket fd,该fd在以后作为这个套接字的唯一标识,类似于普通的文件描述符,可以对其进行读写,结果就是首发消息。
int
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd
< 0){
std::cout<<"socket
error\n";
exit(1);
}
//地址数据结构
sockaddr_in
servaddr;
bzero(&servaddr,
sizeof(servaddr));//清零
servaddr.sin_family
= AF_INET;//ipv4
//端口,22,ssh的端口,原书使用13,但是170没有开放13端口,所以这里使用22,需要htons函数将本地的22转换成网络格式,h表示本地,to转换,n表示network,s表示short
servaddr.sin_port
= htons(22);
//inet_pton将本地的字符串ip地址转换成网络上的格式,在gdb下查看其是一个整数
if(inet_pton(AF_INET,
argv[1], &servaddr.sin_addr) <= 0){
std::cout<<"inet_pton
error for"<
exit(1);
}
//链接,参数是socket fd,地址结构(需要强制转换成sockaddr指针),地址长度
if(connect(sockfd,
(sockaddr *)&servaddr, sizeof(servaddr)) < 0){
std::cout<<"connect
error\n";
exit(1);
}
int n;
const int
MAXLINE = 1024;
char
recvline[MAXLINE];
int sum = 0;
//读取消息,链接到ssh上后,170服务器会返回20个字符长度的字符串“SSH-2.0-OpenSSH_4.3”,这个字符串可能分几次读取出来,最常见的是1次。
while( (n = read(sockfd, recvline, MAXLINE)) > 0){
recvline[n]
= 0;
if(fputs(recvline,
stdout) == EOF){
std::cout<<"fputs
error\n";
exit(1);
}
//原书没有这段,因为13号端口是时间服务器,服务器返回时间后就会断掉socket,所以read就会返回-1,结束循环,但是ssh服务不会主动断掉socket,所以read阻塞,程序没有响应。因此,在收到20个字符后,客户端主动close掉socket。
结束读写有很多种方法,需要自己来定应用层协议,呵呵。
sum += n;
if (sum
>= 20){
close(sockfd);
std::cout<<"finish
reading, close socket\n";
return
0;
}
}
if(n <
0){
std::cout<<"read
error\n";
exit(1);
}
close(sockfd);
return 0;
}
阅读(1052) | 评论(0) | 转发(0) |