server端:
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <syslog.h>
#include <errno.h>
#include <pthread.h>
#define MAX_LISTEN_NUM 5
#define SEND_BUF_SIZE 100
#define RECV_BUF_SIZE 100
#define LISTEN_PORT 2010
#define MAX_CLIENT_NUM 10
typedef struct _tagclientParam{
fd_set fset;
int fd;
int port;
char ipV4Addr[20];
}clientParam;
void* client_thread(void* param);
int main()
{
int listen_sock = 0,maxFd = 0 ;
int ret =0,wrSockIndex =0,i=0;
int wr_sock[MAX_LISTEN_NUM] = {0};
struct sockaddr_in hostaddr;
struct sockaddr_in clientaddr;
int socklen = sizeof(clientaddr);
char sendbuf[SEND_BUF_SIZE] = {0};
char recvbuf[RECV_BUF_SIZE] = {0};
int sendlen = 0;
int recvlen = 0;
int retlen = 0;
int leftlen = 0;
char *ptr = NULL;
pthread_t ptid[MAX_CLIENT_NUM] ;
fd_set serverRFSet,serverSokctSet;
memset((void *)&hostaddr, 0, sizeof(hostaddr));
memset((void *)&clientaddr, 0, sizeof(clientaddr));
hostaddr.sin_family = AF_INET;
hostaddr.sin_port = htons(LISTEN_PORT);
hostaddr.sin_addr.s_addr = htonl(INADDR_ANY);
FD_ZERO(&serverRFSet); //clear rdfds
FD_ZERO(&serverSokctSet); //clear rdfds
listen_sock = socket(AF_INET, SOCK_STREAM, 0);
if(listen_sock < 0)
{
syslog(LOG_ERR, "%s:%d, create socket failed", __FILE__, __LINE__);
exit(1);
}
FD_SET(listen_sock, &serverSokctSet); //add stdin handle into rdfds
if((ret=bind(listen_sock, (struct sockaddr *)&hostaddr, sizeof(hostaddr))) < 0)
{
printf("bind error code: %d \n",ret);
syslog(LOG_ERR, "%s:%d, bind socket failed", __FILE__, __LINE__);
exit(1);
}
if((ret=listen(listen_sock, MAX_LISTEN_NUM)) < 0)
{
syslog(LOG_ERR, "%s:%d, listen failed", __FILE__, __LINE__);
exit(1);
}
while(1){
maxFd = listen_sock +1;
ret = select(maxFd,&serverSokctSet,NULL,NULL,NULL);
switch(ret){
case 0: break;
case -1:{
}break;
default: {
if(FD_ISSET(listen_sock,&serverSokctSet)){
if(wrSockIndex < MAX_CLIENT_NUM){
wr_sock[wrSockIndex] = accept(listen_sock, (struct sockaddr *)&clientaddr, &socklen);
FD_SET(wr_sock[wrSockIndex], &serverRFSet); //add stdin handle into rdfds
ptr = inet_ntoa(clientaddr.sin_addr) ;
sprintf(sendbuf, "welcome %s:%d here!", ptr, clientaddr.sin_port);
sendlen = strlen(sendbuf) +1;
retlen = send(wr_sock[wrSockIndex], sendbuf, sendlen, 0);
if(retlen < 0){
printf("send error \n");
}
clientParam cparm;
存在cparm资源被覆盖的情况,独立变量或者锁
memcpy(cparm.ipV4Addr,ptr,20);
cparm.port = clientaddr.sin_port;
cparm.fd = wr_sock[wrSockIndex];
cparm.fset = serverRFSet;
if(0 != pthread_create(&ptid[wrSockIndex],NULL,client_thread,(void*)(&cparm)) ){
printf("carete error !\n");
}
wrSockIndex++;
}
}
}break;
}
}
for(i=0;i<wrSockIndex;i++)
close(wr_sock[i]);
close(listen_sock);
return 0;
}
//一问一答,应该读和写分开两个线程,not do it now!!!
void* client_thread(void* param){
char recvbuf[RECV_BUF_SIZE] = {0};
int sendlen = 0;
int recvlen = 0;
int retlen = 0;
int leftlen = 0;
char *ptr = NULL;
int maxFd,ret;
clientParam *cparm = (clientParam *)param;
maxFd = cparm->fd +1;
while(1){
ret = select(maxFd,&cparm->fset,NULL,NULL,NULL);
switch(ret){
case 0: break;
case -1:{
}break;
default: {
if(FD_ISSET(cparm->fd,&cparm->fset)){
recvlen = 0;
retlen = 0;
ptr = recvbuf;
leftlen = RECV_BUF_SIZE -1;
retlen = recv(cparm->fd, ptr, leftlen, 0) ;
printf("from %s:%d message: \n",cparm->ipV4Addr,cparm->port);
printf("--->%s\n", ptr);
printf("please input data \n--->");
//scanf("%s",ptr);//不接受空格
gets(ptr);//it is dangerous !!!
if(strcmp("quit",ptr) == 0) goto __end;
sendlen = strlen(ptr) +1;
retlen = send(cparm->fd, ptr, sendlen, 0);
if(retlen < 0)
{
if(errno == EINTR)
retlen = 0;
else
exit(1);
}
}
}
break;
}
}
__end:
close(cparm->fd);
}
clien端:
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <syslog.h>
#include <errno.h>
#include <stdlib.h>
#define MAX_LISTEN_NUM 5
#define SEND_BUF_SIZE 100
#define RECV_BUF_SIZE 100
#define SERVER_PORT 2010
int main()
{
int sock_fd = 0,maxFd;
char recvbuf[RECV_BUF_SIZE] = {0};
char sendbuf[SEND_BUF_SIZE] = {0};
int recvlen = 0;
int retlen = 0;
int sendlen = 0;
int leftlen = 0;
char *ptr = NULL;
struct sockaddr_in ser_addr;
fd_set clientFSet;
memset(&ser_addr, 0, sizeof(ser_addr));
ser_addr.sin_family = AF_INET;
inet_aton("192.168.1.100", (struct in_addr *)&ser_addr.sin_addr);
ser_addr.sin_port = htons(SERVER_PORT);
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
FD_ZERO(&clientFSet); //clear rdfds
FD_SET(sock_fd, &clientFSet); //add stdin handle into rdfds
if(sock_fd < 0)
{
syslog(LOG_ERR, "%s:%d, create socket failed", __FILE__, __LINE__);
exit(1);
}
if(connect(sock_fd, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) < 0)
{
syslog(LOG_ERR, "%s:%d, connect socket failed", __FILE__, __LINE__);
exit(1);
}
maxFd = sock_fd+1;
while(1)
{
//描述符最大值加1
//receive data
switch(select(maxFd,&clientFSet,NULL,NULL,NULL)){
case 0: break;
case -1:{
printf("server is out \n");
goto __end__;
} break;
default: {
if(FD_ISSET(sock_fd,&clientFSet)){
recvlen = 0;
retlen = 0;
ptr = recvbuf;
leftlen = RECV_BUF_SIZE -1;
retlen = recv(sock_fd, ptr, leftlen, 0);
printf("Receive date:\n%s \n", ptr);
printf("please input data \n");
//scanf("%s",ptr);//不接受空格
gets(ptr);//it is dangerous !!!
//printf("\nipnut data:%s \n",ptr);
sendlen = strlen(ptr) +1;
retlen = send(sock_fd, ptr, sendlen, 0);
if(retlen < 0)
{
if(errno == EINTR)
retlen = 0;
else
exit(1);
}
}
}
break;
}
}
__end__:
close(sock_fd);
}
bug:
1、多个client连接server出现server不响应!
2、对于每个程序来说,读取和写需要分开两个线程来实现
仅仅是测试的例子,部分代码摘抄网络!!!!!