- 1. TCP客户端程序实现步骤
- 2. 客户端的实现细节
- 3. 实例
-
创建套接字,准备网路连接
-
请求连接
-
收发数据完成数据交换
-
断开连接
与服务端相比的区别在于请求连接,它是创建客户端套接字后向服务端发起的连接请求。
2. 客户端的实现细节-
connect
函数原型
#include
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 参数说明:
sockfd:客户端套接字的文件描述符
addr:保存目标服务器的地址信息的结构体变量
addrlen:地址长度单位为字节
客户端调用connect函数后,发生以下情况之一才会返回(完成函数调用)
-
服务器接收连接请求 (接收连接请求并不意味着服务端调用了accept函数创建了新的socket与客户端socket 建立了连接,而实际是指服务端把连接请求的信息记录到等待队列中,所以connect函数返回后并不立即进行数据交换)
-
发生断网等异常情况而中断连接请求
-
-
客户端套接字
在下一节的服务端程序中我们会为套接字分配ip和端口,但是,客户端程序中并未出现套接字地址端口数据分配,而是直接创建了套接字之后直接connect函数进行调用,难道客户端程序不需要进行ip和端口的分配?当然不是,网络数据交换必须分配IP和端口。既然如此,那客户端程序套接字是何时、何地、如何进行地址端口分配?
- 何时:调用connect函数时
- 何地:操作系统,更准确的说是在内核中
- 如何:IP用计算机(主机)的IP,端口随机
客户端的地址以及端口在调用connect函数时自动分配,无需调用标记的bind函数进行分配
#include#include #include #include #include #include #include #include int main(int argc,char* argv[]) { int sock = 0; struct sockaddr_in addr = {0}; char* tosend="hello tcp client."; int len = 0; char buf[128] = {0}; int r = 0; if(argc!=3) { printf("Usage:%s n" , argv[0]); } sock = socket(PF_INET, SOCK_STREAM, 0);//创建准备用于连接服务端的套结字,此时创建的是TCP套接字 if( sock == -1 ) { printf("socket errorn"); return -1; } addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(argv[1]); addr.sin_port = htons(atoi(argv[2])); if( connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1 )//用向服务端发起连接请求 { printf("connect errorn"); return -1; } printf("connect successn"); len = send(sock, tosend, strlen(tosend), 0); printf("send bytes = %dn", len); len = 0; do { int i = 0; r = recv(sock, buf, sizeof(buf), 0); if( r > 0 ) { len += r; } for(i=0; i printf("%c", buf[i]); } } while ( r > 0 ); printf("n"); printf("recv bytes = %dn", len); close(sock); return 0; }
可直接使用TCP模拟工具模拟TCP Server端.



