基本TCP套接字编程
来源:互联网 发布:windows抄袭mac os 编辑:程序博客网 时间:2024/05/08 02:36
建立TCO连接就好比一个电话系统。
socket
函数等同于有电话可用;
listen
函数是打开电话振铃;
connect
函数要求我们知道对方的电话号码并拨打他;
accept
函数发生在被呼叫的人应答电话之时,由accept
返回客户的标识。
socket函数
#include <sys/socket.h> int socket(int family, int type, int protocol);
connect函数
#include <sys/socket.h> int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
如果调用connnect
前没有调用bind
函数,内核会确定源IP地址,并选择一个临时端口。
对于TCP套接字,调用connect
函数会激发TCP三路握手过程,出错返回可能有下列情况:
1. TCP客户没有收到SYN
分节的相应,返回ETIMEOUT
错误。
2. 客户的SYN
的相应是RST
,表明该服务器在指定端口没有进程在等待连接,返回ECONNREFUSED
错误。
3. 客户发出的SYN
在中间的某个路由器引发了一个destination unreachable``ICMP
错误,在规定的时间内仍未收到相应,返回EHOSTUNREACH
错误。
若connect
失败,该套接字不可再使用,必须关闭。我们不能再对该套接字调用connect
。
bind函数
#include <sys/socket.h> int bind(int sockfd, const struct sockaddr *myaddr, socklent_t addrlen);
bind函数把一个本地协议地址赋予一个套接字。
要注意是否指定IP地址或端口产生的行为。如果让内核为套接字选择一个临时端口号,bind
函数不返回选择的值(第二个参数有const修饰),需要调用函数getsockname
来返回协议地址。
listen函数
#include <sys/socket.h> int listen(int sockfd, int backlog);
当socket函数创建一个套接字时,它被假设为一个主动套接字(将调用connect
发起连接)。listen
函数把一个未连接的套接字转换为一个被动套接字。
要理解第二个参数,需认识到内核为监听套接字维护的两个队列:
+ 未完成连接队列
+ 已完成连接队列
当一个客户SYN到达时,若这些队列是满的,TCP就忽略该分节(为什么)。
accept函数
#include <sys/socket.h> int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
第一个参数为监听套接字
。若accept
成功,则返回已连接套接字
。注意区分两者(生命期)。
close函数
#include <sys/socket.h> int close(int sockfd);
getsockname和getpeername函数
#include <sys/socket.h> int getsockname(int sockfd, struct sockaddr *localaddr, socketlen_t *addrlen); int getpeername(int sockfd, struct sockaddr *peeraddr, socketlen_t *addrlen);
例程:接受连接并显示客户地址
//server.c #include "unp.h" #include <time.h> int main(int argc, char **argv) { int listenfd, connfd; socklen_t len; struct sockaddr_in servaddr, cliaddr; char buff[MAXLINE]; time_t ticks; size_t i; listenfd = Socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(13); /* daytime server */ Bind(listenfd, (SA *) &servaddr, sizeof(servaddr)); Listen(listenfd, LISTENQ); for ( ; ; ) { len = sizeof(cliaddr); connfd = Accept(listenfd,(SA *)&cliaddr,&len); printf("connection from %s, port %d\n", inet_ntop(AF_INET,&cliaddr.sin_addr,buff,sizeof(buff)), ntohs(cliaddr.sin_port)); ticks = time(NULL); snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks)); // for(i = 0;i<strlen(buff);++i){ // Write(connfd,buff[i],1); // } Write(connfd, buff, strlen(buff)); Close(connfd); } } //client.c #include "unp.h" int main(int argc, char **argv) { int sockfd, n; char recvline[MAXLINE + 1]; struct sockaddr_in servaddr; int counter=0; if (argc != 2) err_quit("usage: a.out <IPaddress>"); if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) err_sys("socket error"); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(13); /* daytime server */ if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) err_quit("inet_pton error for %s", argv[1]); if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0) err_sys("connect error"); while ( (n = read(sockfd, recvline, MAXLINE)) > 0) { counter++; recvline[n] = 0; /* null terminate */ if (fputs(recvline, stdout) == EOF) err_sys("fputs error"); } if (n < 0) err_sys("read error"); //printf("counter = %d\n",counter); exit(0); }
运行服务器程序server
,然后再同一主机上运行客户程序:
./client 127.0.0.1./client 127.0.0.2
得到相应的服务器输出:
connection from 127.0.0.1, port 48235connection from 127.0.0.1, port 48236
- 基本TCP套接字编程
- 基本tcp套接字编程
- 基本TCP套接字编程
- 基本TCP套接字编程
- 基本TCP套接字编程
- 基本TCP套接字编程
- 基本TCP套接字编程
- 基本TCP套接字编程
- TCP基本套接字编程
- 基本TCP套接字编程
- 基本TCP套接字编程
- 基本TCP套接字编程
- 《网络编程》基本 TCP 套接字编程
- 4 基本TCP套接字编程
- TCP/IP_Socket编程 - 基本套接字
- 第四章 基本TCP套接字编程
- 基本 TCP 套接字编程讲解
- 基本的TCP套接字编程
- SparkMLlib之四:Linear Methods
- 理解Intent和Intent Filter
- android 实现自定义键盘的实例
- 保护模式编程初始化
- LeetCode N-Queens
- 基本TCP套接字编程
- oracle-----sql--建表
- Android6.0之运行时权限
- Ubuntu下设置tomcat开启自启动
- 软件测试_BadBoy自动化测试工具8_参数Incrementing Variables
- 2016年1月13日实习日志
- Android webView使用详解
- oracle--sql---约束--视图--索引
- 黑马程序员@java基础中重点之面向对象