您的位置:首页 > 理论基础 > 计算机网络

linux(ubuntu 9.10)下socket(tcp/ip)通信

2010-12-21 22:23 561 查看
参考了一些代码,但是他们的代码总是存在着这样或者那样的问题。

重写了以下,运行成功。

运行服务端代码后,运行客户端,服务端会写出连接来自哪里。服务端无限服务,所以服务端结束的时候要Ctrl+z

其中netdb.h中包含着sockaddr_in 等这一类的数据类型

其中的

fprintf(stderr,xx);

用来向终端输出错误信息stderr 标准输出(设备)文件的意思

int shutdown(int sockfd,int how);

   Sockfd是需要关闭的socket的描述符。参数 how允许为shutdown操作选择以下几种方式:

   ·0-------不允许继续接收数据

   ·1-------不允许继续发送数据

   ·2-------不允许继续发送和接收数据,
struct sockaddr {
unsigned short sa_family; /* 地址族, AF_xxx */
char sa_data[14]; /* 14 字节的协议地址 */
};
struct sockaddr_in {
   short int sin_family; /* 地址族 */
   unsigned short int sin_port; /* 端口号 */
   struct in_addr sin_addr; /* IP地址 */
   unsigned char sin_zero[8]; /* 填充0 以保持与struct sockaddr同样大小 */
};


客户端代码

#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>
#define SERVPORT 3333
#define MAXDATASIZE 100 /*为每次最大数据传输量 */
int main(int argc,char * argv[])
{
int sockfd,recvbytes;
char buf[MAXDATASIZE];
hostent *host;
sockaddr_in serv_addr;
if(argc<2)
{
fprintf(stderr,"Please enter the server's hostname!/n");
exit(1);
}
if((host=gethostbyname(argv[1]))==NULL)
{
perror("gethostbyname error");
exit(1);
}
if((sockfd=socket(AF_INET, SOCK_STREAM,0))==-1)
{
perror("socket creating error");
exit(1);
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERVPORT);
serv_addr.sin_addr=*((struct in_addr *)host->h_addr);
bzero(&(serv_addr.sin_zero),8);
if(connect(sockfd,(struct sockaddr *) &serv_addr ,sizeof(struct sockaddr))==-1)
{
perror("connecting error");
exit(1);
}
if((recvbytes=recv(sockfd,buf,MAXDATASIZE,0))==-1)
{
perror("recv error");
exit(1);
}
buf[recvbytes]='/0';
shutdown(sockfd,2);

return 0;
}

()函数原型为:

   int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen);

  该函数比send()函数多了两个参

服务端代码

#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 <sys/wait.h>
#include <unistd.h>
#define SERVPORT 3333
#define BACKLOG 10
int main()
{
int sockfd,client_fd;
socklen_t sin_size;
sockaddr_in my_addr;
sockaddr_in remote_addr;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket creating error");
exit(1);
}
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(SERVPORT);
my_addr.sin_addr.s_addr=INADDR_ANY;
bzero(&(my_addr.sin_zero),8);
if(bind(sockfd,(sockaddr *)&my_addr, sizeof(struct sockaddr))==-1)
{
perror("bind出错");
exit(1);
}
if(listen(sockfd,BACKLOG)==-1)
{
perror("can not listen to the port");
exit(1);
}
while(1)
{
sin_size=sizeof(sockaddr_in);
if((client_fd= accept(sockfd,(sockaddr *)&remote_addr,&sin_size))==-1)
{
perror("accept error");
continue;
}
printf("received a connection from %s/n",inet_ntoa(remote_addr.sin_addr));
if(!fork())
{
if(send(client_fd,"hello, you are connected!/n",26,0)==-1)
perror("send error");
shutdown(client_fd,2);
exit(0);
}
shutdown(client_fd,2);
}
return 0;
}


同时关于fork的说明,fork创建一个父进程的副本,但是却不尽相同。

fork函数返回两个值,一个是返回到子进程,得到一个0的值

另一个是返回到父进程,得到的是子进程的id,这样父子进程就可以分别执行不同的任务,如果分配不成功,则返回父进程-1

例如,执行如下代码

#include <unistd.h>
#include <iostream>
#include <stdio.h>
int main()
{
int threadID=0;
threadID=fork();
if(threadID<0)
{
printf("creating child process error/n");
}
else if(threadID==0)
{
printf("thread %d threadid is %d is running/n ",getpid(),threadID);
}
else
{
printf("this is the father process%d/n and it's child threadid is%d/n ",getpid(),threadID);
}
return 0;
}


将得到

this is the father process3112

and it's child threadid is3113

thread 3113 threadid is 0 is running
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: