在完成老师的linux课堂作业时,获益良多,感谢老师的指导和帮助,同时分享一下我的代码以及一些注意事项,希望大家都能少走一些弯路,也欢迎大家进行指导或者探讨。
客户机样式为./可执行文件 默认网络ip
服务机端一直等待客户端的连接请求,接受连接后,则服务机端会创建一个线程用于发送数据,另一个线程用于接收数据,当发送88时退出程序
.
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
#include <pthread.h>
#define LENGTH 512 //发送数据长度
#define PORT 5000 //套接字所用端口号
#define BACKLOG 10 //最大监听数
void* recv1(int nsockfd)
{
int num;
char recvBuf[LENGTH];
memset(recvBuf,0,sizeof(recvBuf));
while(1)
{
num = recv(nsockfd,recvBuf,sizeof(recvBuf),0);
if(num > 0)
{
printf("host receive: %s \n", recvBuf);
}
else break;
}
}
void* send1(void* args)
{
int sockClient1;
char buff1[LENGTH];
sockClient1 = *((int*)args);//套接字
while(1)
{
scanf("%s",buff1);
if(buff1 == " ")
{
break;
}
int e = send(sockClient1,buff1,sizeof(buff1),0);
if(e == -1)
{
printf("发送失败!");
break;
}
printf("host send: %s\n", buff1);
if(strcmp(buff1,"88") == 0)
{
close(sockClient1);
exit(1);
}
}
}
int main(void)
{
int sockfd; //建一个套接字,用于监听
int nsockfd;//建立通讯的套接字
int sin_size; //结构体长度
int ret;//发送线程的返回
struct sockaddr_in addr_host;//本机地址信息
struct sockaddr_in addr_remote;//客户端地址信息
char buf[]= {"Host: hello, I'm a server !(QAQ)!"};
if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("ERROR: Failed to obtain Socket Despcritor.\n");
return 0;
}
else
{
printf("OK: Bind the Port %d sucessfully.\n",PORT);
}
bzero(&addr_host, sizeof(struct sockaddr_in));//清零后再初始化端口
addr_host.sin_family = AF_INET;
addr_host.sin_port = htons(PORT);
addr_host.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sockfd,(struct sockaddr*)&addr_host,sizeof(struct sockaddr)) == -1)
{
printf ("ERROR: Failed to bind Port %d.\n",PORT);
return (0);
}
else
{
printf("OK: Bind the Port %d sucessfully.\n",PORT);
}
if(listen(sockfd,BACKLOG) == -1)
{
printf ("ERROR: Failed to listen Port %d.\n", PORT);
return (0);
}
else
{
printf ("OK: Listening the Port %d sucessfully.\n", PORT);
}
while(1)
{
/*等待客户请求*/
sin_size = sizeof(struct sockaddr_in);
if((nsockfd = accept(sockfd,(struct sockaddr *)&addr_remote,&sin_size))== -1)
{
printf ("ERROR: Obtain new Socket Despcritor error.\n");
continue;
}
else
{
/*inet_ntoa将一个网络字节序的IP地址(结构体型)转化为点分十进制(字符串)*/
printf ("OK: Server has got connect from %s.\n", inet_ntoa(addr_remote.sin_addr));
}
/*发送数据*/
int iSend = send(nsockfd,buf,sizeof(buf),0);
if(iSend == -1)
{
printf("发送失败\n");
break;
}
pthread_t tids[2];
if((ret = pthread_create(&tids[0],NULL,send1,(void*)&nsockfd)) != 0)
{
printf("pthread_creat error\n");
}
recv1(nsockfd);
close(nsockfd);
}
close(sockfd);
}
客户机端先建立socket,通过connect()请求连接,建立连接成功后,客户机端会创建一个线程用于发送数据,另一个线程用于接收数据,当接收到88时退出程序
.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#define LENGTH 512 //发送数据长度
#define PORT 5000 //套接字所用端口号
void* recv1(int nsockfd)
{
int num;
char recvBuf[LENGTH];
memset(recvBuf,0,sizeof(recvBuf));
while(strcmp(recvBuf,"88") != 0)
{
num = recv(nsockfd,recvBuf,sizeof(recvBuf),0);
if(num > 0)
{
printf("client receive: %s \n", recvBuf);
}
else break;
}
}
void* send1(void* args)
{
int sockClient1;
char buff1[LENGTH];
sockClient1 = *((int*)args);
while(1)
{
scanf("%s",buff1);
if(buff1 == " ")
{
break;
}
int e = send(sockClient1,buff1,sizeof(buff1),0);
if(e == -1)
{
printf("发送失败!");
break;
}
printf("client send: %s\n",buff1);
}
}
int main(int argc,char *argv[]) //从终端里读取参数,
{
int sockfd;
int ret; //创建线程的返回值
char buff[LENGTH];
memset(buff,0,sizeof(buff));
struct sockaddr_in remote_addr;
if(argc != 2)
{
printf ("error: 请输入Client HOST IP (例如: ./client 192.168.0.94).\n");
return 0;
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("ERROR: Failed to obtain Socket Descriptor!\n");
return (0);
}
bzero(&remote_addr,sizeof(remote_addr)); //清零后再初始化端口
remote_addr.sin_family = AF_INET; // Protocol Family
remote_addr.sin_port = htons(PORT); // Port number
inet_pton(AF_INET, argv[1], &remote_addr.sin_addr); // Net Address
if (connect(sockfd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)) == -1)
{
printf ("ERROR: Failed to connect to the host!\n");
return (0);
}
else
{
printf ("OK: Have connected to the %s\n",argv[1]);
pthread_t tids[2];
ret = pthread_create(&tids[0],NULL,send1,(void*)&sockfd);
if(ret != 0)
{
printf("pthread_creat error\n");
}
recv(sockfd, buff,sizeof(buff), 0);
printf("%s\n",buff);
}
recv1(sockfd);
//send1((void*)&sockfd);
close(sockfd);
}
再用kill -9 端口号对应的PID,杀死该进程,这样可以防止端口号被占用,出现bind绑定失败的情况。