可通过以下程序测试socket发送和接收时,缓冲区buf的大小:
server端:
struct ps{
int st;
pthread_t *thr;
};
#define MAXBUF 131072
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int status = 0;
void *recvsocket(void *arg) //接收client端socket数据的线程
{
struct ps *p = (struct ps *)arg;
int st = p->st;
char s[1024];
char *pp = malloc(MAXBUF);
while(1)
{
char buf[100];
read(STDIN_FILENO, buf, sizeof(buf));
memset(s, 0, sizeof(s));
int rc = recv(st, pp, MAXBUF, 0);
printf("rc =%d\n", rc);
if(rc <= 0) //如果返回小于等于0,代表socket已经关闭或者出错
break;
// printf("%s\n",s);
}
pthread_mutex_lock(&mutex);
status = 0;
pthread_mutex_unlock(&mutex);
pthread_cancel(*(p->thr)); //被cancel掉的线程内部没有使用锁。
return NULL;
}
void *sendsocket(void *arg) //发送server端socket数据的线程
{
int st = *(int *)arg;
char s[1024];
while(1)
{
memset(s, 0, sizeof(s));
read(STDIN_FILENO, s, sizeof(s)); //从键盘读取用户输入信息
send(st, s, strlen(s), 0);
}
return NULL;
}
int main(int arg, char *args[])
{
if(arg < 2)
{
return -1;
}
int port = atoi(args[1]);
int st = socket(AF_INET, SOCK_STREAM, 0); //初始化socket
int on = 1;
if(setsockopt(st, SOL_SOCKET, SO_REUSEADDR,&on, sizeof(on)) == -1)
{
printf("setsockoptfailed %s\n", strerror(errno));
return EXIT_FAILURE;
}
struct sockaddr_in addr; //定义一个IP地址的结构
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET; //设置addr结构的属性定位为TCP/IP地址
addr.sin_port = htons(port); //将本地字节顺序转化为网络字节数据
addr.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY代表这个server上所有的地址
//将IP地址与server程序绑定
if(bind(st, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
printf("connectfailed %s\n", strerror(errno));
return EXIT_FAILURE;
}
//server端开始listen,
if(listen(st, 20) == -1)
{
printf("listenfailed %s\n", strerror(errno));
return EXIT_FAILURE;
}
int client_st = 0;//client端socket
// socklen_t len = 0;
struct sockaddr_in client_addr; //表示client端的IP地址
//void *p = &client_addr;
pthread_t thrd1, thrd2;
while(1)
{
memset(&client_addr, 0, sizeof(client_addr));
socklen_t len = sizeof(client_addr);
//accept会阻塞,直到有客户端连接过来,accept返回client的socket描述符
client_st = accept(st, (struct sockaddr *)&client_addr,&len);
pthread_mutex_lock(&mutex); //为全局变量加一个互斥锁,防止与线程函数同时读写变量的冲突
status++;
pthread_mutex_unlock(&mutex); //解锁
if(status > 1) //代表这是第二个socket连接,关闭(确保只能连接一个socket)
{
close(client_st);
continue;
}
if(client_st == -1)
{
printf("acceptfailed %s\n", strerror(errno));
return EXIT_FAILURE;
}
printf("accept by%s\n", inet_ntoa(client_addr.sin_addr));
struct ps ps1;
ps1.st = client_st;
ps1.thr = &thrd2;
pthread_create(&thrd1, NULL, recvsocket, &ps1);
pthread_detach(thrd1); //设置线程为可分离
// pthread_create(&thrd2, NULL, sendsocket, &client_st);
// pthread_detach(thrd2); //设置线程为可分离
}
close(st); //关闭server端listen的socket
return EXIT_SUCCESS;
}
client端:
#define MAXBUF 131072*4
void *recvsocket(void *arg) //接收client端socket数据的线程
{
int st = *(int *)arg;
char s[1024];
while(1)
{
memset(s, 0, sizeof(s));
int rc = recv(st, s, sizeof(s), 0);
if(rc <= 0) //如果返回小于等于0,代表socket已经关闭或者出错
{
break;
}
printf("%s\n", s);
}
return NULL;
}
void *sendsocket(void *arg) //发送server端socket数据的线程
{
int st = *(int *)arg;
char s[1024];
char *p = malloc(MAXBUF); //
while(1)
{
memset(s, 0, sizeof(s));
read(STDIN_FILENO, s, sizeof(s)); //从键盘读取用户输入信息
int rc = send(st, p, MAXBUF, 0);
printf("rc =%d\n", rc);
}
return NULL;
}
int main(int arg, char *args[])
{
if(arg < 3)
return -1;
int port = atoi(args[2]);
int st = socket(AF_INET, SOCK_STREAM, 0); //初始化socket
struct sockaddr_in addr; //定义一个IP地址的结构
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET; //设置结构地址类型为TCP/IP地址
addr.sin_port = htons(port); //指定一个端口号:8080,htons:将short类型从host字节类型到net字节类型转化
addr.sin_addr.s_addr = inet_addr(args[1]); //将字符串类型的IP地址转化为int,赋给addr结构
//调用connect连接到结构addr指定的IP地址和端口号
if(connect(st, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
printf("connectfailed %s\n", strerror(errno));
return EXIT_FAILURE;
}
pthread_t thrd1, thrd2;
pthread_create(&thrd1, NULL, recvsocket, &st);
pthread_create(&thrd2, NULL, sendsocket, &st);
pthread_join(thrd1, NULL);
//pthread_join(thrd2, NULL);
close(st); //关闭socket
return EXIT_SUCCESS;
}
运行结果如下:
一次发送了521k的数据,服务器端分4次接收(服务端程序中设置的是每按下回车键一次,接收一次数据)。
经测试,centos64系统的接收端的缓冲区大小是128k。