基于TCP的服务器端/客户端(一)---------网络编程(linux----C)
2016-12-17 11:30
671 查看
基于TCP的服务器端/客户端(一)---------网络编程(linux----C)
1、TCP/IP协议
2、TCP/UDP层
3、TCP服务器端的默认函数调用顺序
(1)进入等待连接请求状态
只有调用了listen函数,客户端才能进入可发出连接请求的状态。即,这时客户端才能调用connect函数(若提前调用将发生错误)。
函数:#include <sys/socket.h>
int listen(int sock,int backlog);
成功时返回0,失败时返回-1。
参数:
sock:希望进入等待连接请求状态的套接字文件描述符,传递的描述符套接字参数成为服务器端套接字(监听套接字)。
backlog:连接请求等待队列(Queue)的长度,若为5,则队列长度为5,表示最多使5个连接请求进入队列。
(2)受理客户端连接请求
函数:#include <sys/socket.h>
int accept(int sock,struct sockaddr *addr,socklen_t *addrlen);
成功时返回创建的套接字文件描述符,失败时返回-1。
参数:
sock:服务器套接字的文件描述符。
addr:保存发起连接请求的客户端地址信息的变量地址值,调用函数后向传递来的地址变量参数填充客户端地址信息。
addrlen:第二个参数addr结构体的长度,但是存有长度的变量地址。函数调用完成后,该变量即被填入客户端地址长度。
实例1、Hello world服务器端
4、TCP客户端的默认函数调用顺序
函数:#include <sys/socket.h>
int connect(int sock,struct sockaddr*servaddr,socklen_t addrlen);
成功返回0,失败返回-1。
参数:
sock:客户端套接字文件描述符。
servaddr:保存目标服务器端地址信息的变量地址值。
addrlen:以字节为单位传递已传递给第二个结构体参数servaddr地址变量长度。
实例1、Hello world客户端
hello_client.c代码:
5、基于TCP的服务器端/客户端函数调用关系
6、实现迭代服务器/客户端
(1)实现迭代服务器
实例1、回声服务器端
echo_server.c代码:
[/code]
迭代回声客户端
echo_client.c代码:
1、TCP/IP协议
2、TCP/UDP层
3、TCP服务器端的默认函数调用顺序
(1)进入等待连接请求状态
只有调用了listen函数,客户端才能进入可发出连接请求的状态。即,这时客户端才能调用connect函数(若提前调用将发生错误)。
函数:#include <sys/socket.h>
int listen(int sock,int backlog);
成功时返回0,失败时返回-1。
参数:
sock:希望进入等待连接请求状态的套接字文件描述符,传递的描述符套接字参数成为服务器端套接字(监听套接字)。
backlog:连接请求等待队列(Queue)的长度,若为5,则队列长度为5,表示最多使5个连接请求进入队列。
(2)受理客户端连接请求
函数:#include <sys/socket.h>
int accept(int sock,struct sockaddr *addr,socklen_t *addrlen);
成功时返回创建的套接字文件描述符,失败时返回-1。
参数:
sock:服务器套接字的文件描述符。
addr:保存发起连接请求的客户端地址信息的变量地址值,调用函数后向传递来的地址变量参数填充客户端地址信息。
addrlen:第二个参数addr结构体的长度,但是存有长度的变量地址。函数调用完成后,该变量即被填入客户端地址长度。
实例1、Hello world服务器端
hello_server.c代码: #include<stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include<sys/socket.h> void error_handling(char *message); int main(int argc,char *argv[]) { int serv_sock; int clnt_sock; struct sockaddr_in serv_addr; struct sockaddr_in clnt_addr; socklen_t clnt_addr_size; char message[]="Hello world!"; if(argc!=2) { printf("Usage:%s <port>\n",argv[0]); exit(1); } serv_sock=socket(PF_INET,SOCK_STREAM,0); //调用socket函数创建套接字 if(serv_sock== -1) { error_handling("socket()error"); } memset(&serv_addr,0,sizeof(serv_addr)); serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); serv_addr.sin_port=htons(atoi(argv[1])); if(bind(serv_sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1)//调用bind函数分配IP地址和端口号 error_handling("bind()error"); if(listen(serv_sock,5)==-1) //调用listen函数将套接字转为可接收连接状态 error_handling("listen() error"); clnt_addr_size=sizeof(clnt_addr); clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_addr,&clnt_addr_size); //调用accept函数受理连接请求。 //如果在没有连接请求的情况下调用该函数,则不会返回,直到有连接请求为止。 if(clnt_sock==-1) error_handling("accept()error"); write(clnt_sock,message,sizeof(message)); // close(clnt_sock); close(serv_sock); return 0; } void error_handling(char *message) { fputs(message,stderr); fputc("\n",stderr); exit(1); }
4、TCP客户端的默认函数调用顺序
函数:#include <sys/socket.h>
int connect(int sock,struct sockaddr*servaddr,socklen_t addrlen);
成功返回0,失败返回-1。
参数:
sock:客户端套接字文件描述符。
servaddr:保存目标服务器端地址信息的变量地址值。
addrlen:以字节为单位传递已传递给第二个结构体参数servaddr地址变量长度。
实例1、Hello world客户端
hello_client.c代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> void error_handling(char *message); int main(int argc,char *argv[]) { int sock; struct sockaddr_in serv_addr; char message[30]; int str_len=0; int idx=0,read_len=0; if(argc!=3) { printf("Usage:%s<IP><port>\n",argv[0]); exit(1); } sock=socket(PF_INET,SOCK_STREAM,0);//创建套接字,但此时套接字并不马上分为服务器端和客户端。 //如果紧接着调用bind、listen函数,将成为服务器端套接字;如果调用connect函数,将成为客户端套接字。 if(sock==-1) error_handling("socket() error"); memset(&serv_addr,0,sizeof(serv_addr)); serv_addr.sin_family=AF_INET; serv_addr.sin_addr.s_addr=inet_addr(argv[1]); serv_addr.sin_port=htons(atoi(argv[2])); if(connect(sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1) //调用connect函数向服务器端发送连接请求。 error_handling("connect() error!"); while(read_len=read(sock,&message[idx++],1)) { if(read_len==-1) error_handling("read()error!"); str_len+=read_len; } printf("Message from server:%s\n",message); printf("Function read call count:%d\n",str_len); close(sock); return 0; } void error_handling(char *message) { fputs(message,stderr); fputc("\n",stderr); exit(1); }
5、基于TCP的服务器端/客户端函数调用关系
6、实现迭代服务器/客户端
(1)实现迭代服务器
实例1、回声服务器端
echo_server.c代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 1024 void error_handling(char *message); int main(int argc,char *argv[]) { int serv_sock, clnt_sock; char messag[1024]; int str_len, i; struct sockaddr_in serv_adr, clnt_adr; socklen_t clnt_adr_sz; if(argc!=2) { printf("Usage:%s<port>\n",argv[0]); exit(1); } serv_sock=socket(PF_INET,SOCK_STREAM,0); if(serv_sock==-1) error_handling("socket()error"); memset(&serv_adr,0,sizeof(serv_adr)); serv_adr.sin_family=AF_INET; serv_adr.sin_addr.s_addr=htonl(INADDR_ANY); serv_adr.sin_port=htons(atoi(argv[1])); if(bind(serv_sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr))==-1) error_handling("bind()error"); if(listen(serv_sock,5)==-1) error_handling("listen()error"); clnt_adr_sz=sizeof(clnt_adr); for(i=0;i<5;i++) { clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_adr,&clnt_adr_sz); if(clnt_sock==-1) error_handling("accept()error"); else printf("Connected client %d \n",i+1); while((str_len=read(clnt_sock,messag,1024))!=0) write(clnt_sock,messag,str_len); close(clnt_sock); } close(serv_sock); return 0; } void error_handling(char *message) { fputs(message,stderr); fputc('\n',stderr); exit(1); }
编译与运行
编译:gcc echo_server.c -o eserver
执行:./eserver 9190
[/code]
迭代回声客户端
echo_client.c代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> void error_handling(char *message); int main(int argc,char *argv[]) { int sock; char message[1024]; int str_len; struct sockaddr_in serv_adr; if(argc!=3) { printf("Usage:%s<IP><port>\n",argv[0]); exit(1); } sock=socket(PF_INET,SOCK_STREAM,0); if(sock==-1) error_handling("socket()error"); memset(&serv_adr,0,sizeof(serv_adr)); serv_adr.sin_family=AF_INET; serv_adr.sin_addr.s_addr=inet_addr(argv[1]); serv_adr.sin_port=htons(atoi(argv[2])); if(connect(sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr))==-1) error_handling("connect()error"); else puts("Connected.........."); while(1) { fputs("Input message(Q to quit):",stdout); fgets(message,1024,stdin); if(!strcmp(message,"q\n")||!strcmp(message,"Q\n")) break; write(sock,message,strlen(message)); str_len=read(sock,message,1024-1); message[str_len]=0; printf("Message from server:%s",message); } close(sock); return 0; } void error_handling(char *message) { fputs(message,stderr); fputc('\n',stderr); exit(1); }
编译与运行
编译:gcc echo_client.c -o eclient
执行:./eclient 127.0.0.1 9190
相关文章推荐
- 基于TCP的服务器端/客户端(二)---------网络编程(Linux----C)
- 基于UDP的服务器端/客户端---------网络编程(Linux----C)
- 【Linux网络编程】基于TCP多进程(fork)版本客户端/服务器
- linux网络编程,将服务器端时间通过tcp传送到客户端
- 【Linux网络编程】基于TCP单进程版本阻塞式客户端/服务器
- 基于Linux的TCP网络编程
- linux网络编程之socket(九):使用select函数改进客户端/服务器端程序
- linux网络编程之TCP/IP基础(五):分析一帧基于UDP的TFTP协议帧
- WINDOWS (服务器) 和 DOS(客户端) 网络互连 基于TCP/IP的编程实现
- Linux网络编程-客户端与服务器端异步通信
- 黑马程序员--10.网络编程--05.【TCP协议相关类】【InetSocketAddress类】【Socket类】【ServerSocket类】【TCP客户端和服务器端】
- Linux网络编程:基于TCP的程序开发回顾篇
- linux socket网络编程二 基于tcp
- 基于Linux的TCP网络编程
- Linux网络编程一步一步学-客户端和服务器端互相收发消息
- 基于Linux的TCP网络编程
- WINDOWS (服务器) 和 DOS(客户端) 网络互连 基于TCP/IP的编程实现
- Linux网络编程:基于TCP的程序开发回顾篇
- Linux网络编程-客户端与服务器端通信
- linux网络编程--服务器客户端(TCP实现)