实验五 关于tcp套接字编程
一、 实验目的
1熟悉基本TCP套接字编程流程(服务器端、客户端) 2掌握流程中的关键函数的用法 二、 实验要求
1 将实例程序录入、编译、运行,写出运行结果
2 写出套接字定义相关的语句(服务器端、客户端分开写)
3 写出能体现TCP套接字编程流程的语句(服务器端、客户端分开写) 4 写出除上诉相关语句及头文件之外的语句注释 三、实例程序 服务器端
客户端
运行:
运行服务器端程序 ./服务器端程序名称
运行客户端程序 ./客户端程序名称+空格+127.0.0.1
服务器端
1. #include
8. #include
10. #define BACKLOG 1 //最大允许连接的数量BACKLOG定义为1 11. main() 12. {
13. int listenfd,connectfd; 14. struct sockaddr_in server; 15. struct sockaddr_in client; 16. socklen_t addrlen;
17. if ((listenfd =socket(AF_INET,SOCK_STREAM, 0))== -1) 18. {
19. perror(\20. exit(1);
21. } //17~21行:调用socket()函数,产生TCP套接字。如果出错,打印
错误信息。
22. int opt=SO_REUSEADDR;
23. setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
//22~23行:设置套接字选项SO_REUSEADDR,即地址重用选项。由于系统默认是只允许一个套接字绑定在一个特定的协议地址上,并且当该套接字关闭后,系统仍不允许在该地址上绑定其它套接字。如果去掉这两行,程序运行时产生的错误信息为:Bind() error;Address already in use. 24. bzero(&server,sizeof(server)); 25. server.sin_family=AF_INET; 26. server.sin_port=htons(PORT);
27. server.sin_addr.s_addr=htonl(INADDR_ANY);
//24`27行:初始化server套接字地址结构,并对地址结构中的成员赋值。当前的本地地址设为INADDR_ANY,接收目的地址是本机IP的客户端连接,这里的端口号和IP地址都要转换成网络字节序。
28. if (bind(listenfd,(struct sockaddr *)&server,sizeof(server))==-1) 29. {
30. perror(\31. exit(1);
32. } //28~32行:将套接字和指定的协议地址绑定. 33. if(listen(listenfd,BACKLOG)==-1) 34. {
35. perror(\36. exit(1);
37. } //33~37行:将套接字描述符转换成监听描述符,等待客户的连接. 38. addrlen=sizeof(client);
39. if((connectfd=accept(listenfd,(struct sockaddr*)&client,&addrlen))
==-1) 40. {
41. perror(\42. exit(1);
43. } //39~43行:接受客户连接,客户的地址信息存放在client地址结构中.
44. printf(\
inet_ntoa(client.sin_addr),htons(client.sin_port));
//显示客户的IP地址和端口号通过inet_ntoa()函数将IP地址转换成可显示的ASCII字符串,通过htons()函数将端口号转换成网络字节序。
45. send(connectfd,\发送Welcome字符串给客户端 46. close(connectfd);
47. close(listenfd); //46~47行:关闭套接字。线关闭已连接套接字,再关闭
监听套接字 48. }
客户端
1.#include
8.#include
10.#define MAXDATASIZE 100 //接收缓冲器大小为100 11.int main(int argc,char *argv[]) 12.{
13.int sockfd,num;
14.char buf[MAXDATASIZE]; 15.struct hostent *he;
16.struct sockaddr_in server;
17.if (argc !=2) 18.{
19.printf(\20.exit(1);
21.} //17~21行:检查用户的输入。如果用户输入不正确,提示用户正确的输入方式
22.if((he=gethostbyname(argv[1]))==NULL) 23.{
24.printf(\25.exit(1);
26.} //22~26行:通过用户输入的点分十进制形式的IP地址,获得服务器的相关地址信息
27.if ((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) 28.{
29.printf(\30.exit(1);
31.} //27~31行:调用socket()函数产生套接字描述符 32.bzero(&server,sizeof(server)); 33.server.sin_family=AF_INET; 34.server.sin_port=htons(PORT);
35.server.sin_addr=*((struct in_addr *)he->h_addr); //32~35行:初始化服务器的地址结构,并为地址结构的成员赋值
36.if(connect(sockfd,(struct sockaddr *)&server,sizeof(server))==-1)
37.{
38.printf(\39.exit(1);
40.} //36~40行:调用connect()函数连接到服务器server 41.if ((num=recv(sockfd,buf,MAXDATASIZE,0))==-1) 42.{
43.buf[num-1]='\\0'; 44.exit(1);
45.} //41~45行:接收服务器发过来的字符串,保存在buf中。接收的真正字节数被存储在num中。
46.buf[num-1]='\\0'; //以\\0标志字符串的结束
47.printf(\显示从服务器接收到的buf信息
48.close(sockfd); //关闭套接字 49.}