1.解决
Address already in use
很多网络问题都可以通过编写client 和server 的两个简单小程序来进行验证,一般验证过程都需要不断重启client 或server,当
不断重启client 或者sever的时候经常会出现Address already in use 这样的错误,至于这个到底是什么原因,网上一大堆,我就
不记录了,贴一个ibm的解释网址是
http://www.ibm.com/developerworks/cn/linux/l-sockpit/。
bind 普遍遭遇的问题是试图绑定一个已经在使用的端口。该陷阱是也许没有活动的套接字存在,但仍然禁止绑定端口(bind 返回 EADDRINUSE),它由 TCP 套接字状态 TIME_WAIT 引起。该状态在套接字关闭后约保留 2 到 4 分钟。在 TIME_WAIT 状态退出之后,套接字被删除,该地址才能被重新绑定而不出问题。等待 TIME_WAIT 结束可能是令人恼火的一件事,特别是如果您正在开发一个套接字服务器,就需要停止服务器来做一些改动,然后重启。幸运的是,有方法可以避开 TIME_WAIT 状态。可以给套接字应用 SO_REUSEADDR 套接字选项,以便端口可以马上重用。
下面的client 和server 代码是网上抄来的,方便以后测试用,server的代码已经通过设置 SO_REUSEADDR 为允许地址重用(on=1),on=0 表示禁止地址重用,要是需要不断重启client 的话,就可以参照server的代码设置socke 可以重用的标志
server.c
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
-
#define BUFFER_SIZE 40
-
-
int main()
-
{
-
char buf[BUFFER_SIZE];
-
int server_sockfd, client_sockfd;
-
int sin_size=sizeof(struct sockaddr_in);
-
struct sockaddr_in server_address;
-
struct sockaddr_in client_address;
-
memset(&server_address,0,sizeof(server_address));
-
server_address.sin_family = AF_INET;
-
server_address.sin_addr.s_addr = INADDR_ANY;
-
server_address.sin_port = htons(12000);
-
-
if((server_sockfd = socket(AF_INET, SOCK_STREAM, 0))<0)
-
{
-
perror("server_sockfd creation failed");
-
exit(EXIT_FAILURE);
-
}
-
-
int on=1;
-
if((setsockopt(server_sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)))<0)
-
{
-
perror("setsockopt failed");
-
exit(EXIT_FAILURE);
-
}
-
-
if((bind(server_sockfd,(struct sockaddr *)&server_address,sizeof(struct sockaddr)))<0)
-
{
-
perror("server socket bind failed");
-
exit(EXIT_FAILURE);
-
}
-
-
listen(server_sockfd,5);
-
-
client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_address,(socklen_t*)&sin_size);
-
if(client_sockfd<0)
-
{
-
perror("accept client socket failed");
-
exit(EXIT_FAILURE);
-
}
-
-
if(recv(client_sockfd,buf,BUFFER_SIZE,0)<0)
-
{
-
perror("recv client data failed");
-
exit(EXIT_FAILURE);
-
}
-
printf("receive from client:%s/n",buf);
-
-
if(send(client_sockfd,"I have received your message.",BUFFER_SIZE,0)<0)
-
{
-
perror("send failed");
-
exit(EXIT_FAILURE);
-
}
-
close(client_sockfd);
-
close(server_sockfd);
-
exit(EXIT_SUCCESS);
-
}
client.c
opy
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
-
#define BUFFER_SIZE 40
-
-
int main()
-
{
-
char buf[BUFFER_SIZE];
-
int client_sockfd;
-
int len;
-
struct sockaddr_in address;
-
int result;
-
client_sockfd = socket(AF_INET, SOCK_STREAM, 0);
-
address.sin_family = AF_INET;
-
address.sin_addr.s_addr = inet_addr("127.0.0.1");
-
address.sin_port = htons(12000);
-
len = sizeof(address);
-
-
result = connect(client_sockfd, (struct sockaddr *)&address, len);
-
if(result<0)
-
{
-
perror("connect failed");
-
exit(EXIT_FAILURE);
-
}
-
printf("Please input the message:");
-
scanf("%s",buf);
-
send(client_sockfd,buf,BUFFER_SIZE,0);
-
recv(client_sockfd,buf,BUFFER_SIZE,0);
-
printf("receive data from server: %s/n",buf);
-
close(client_sockfd);
-
return 0;
-
}
2. 利用telnet 测试三次握手和http request的过程
server 10.0.1.1 ,开启http 服务
client :telnet 10.0.1.1 80 , 然后会出现以下的返回结果,这个时候就是完成了三次握手(socket是阻塞的)
然后接着输入GET ,回车就可以得到返回结果,如下图,至于http request 的请求头,可以
根据自己的需求输入,如果有多行的请求头,可能要先用个记事本写好,再拷贝到telnet 下面,因为telnet中一回车,
就应该是发送了这个request了(多行请求头的这个没有测试过)
3. 三次握手成功后,网卡down 了,send 的返回值
阻塞状态的,直接用telnet 测试了,send 一直没有返回,阻塞在那里
非阻塞状态的,写了个小代码测试,send 返回值是
阅读(1827) | 评论(0) | 转发(0) |