linux 下socket(Linux怎么学)
大家好,感谢邀请,今天来为大家分享一下linux 下socket的问题,以及和Linux怎么学的一些困惑,大家要是还不太明白的话,也没有关系,因为接下来将为大家分享,希望可以帮助到大家,解决大家的问题,下面就开始吧!
socket在windows下和linux下的区别
1)头文件
windows下winsock.h/winsock2.h
linux下sys/socket.h错误处理:errno.h
2)初始化
windows下需要用WSAStartup
WSADATA wsaData;
err= WSAStartup(0x202,&wsaData);
if( err!= 0)
{
return 0;
}
else if( LOBYTE( wsaData.wVersion)!= 2|| HIBYTE( wsaData.wVersion)!= 2)//检测是否支持这个版本的socket
{
WSACleanup();
return 0;
}
对应的退出清理用WSACleanup();
linux下不需要
3)关闭socket
windows下closesocket(...)
linux下close(...)
4)socket类型
windows下SOCKET
linux下int
5)获取错误码
windows下WSAGetLastError()
linux下errno变量
extern int errno;
int geterror(){return errno;}
6)设置非阻塞
windows下ioctlsocket(server_socket,FIONBIO,&ul); int ul= 1
linux下fcntl(server_socket,F_SETFL, O_NONBLOCK);<fcntl.h>
7)send函数最后一个参数
windows下一般设置为0
linux下必须是后几个参数用到的socket中,值最大的数(整型)加1(另一种说法是设置为MSG_NOSIGNAL)
8)毫秒级时间获取
windows下GetTickCount()
linux下gettimeofday()
9)编译连接
windows下ws2_32.lib
linux下
连接是使用参数:-lstdc
运行时需要libstdc++.so.5,可在/usr/lib目录中创建一个链接。
10)Socket操作错误返回值
都为SOCKET_ERROR,他的值是-1
11)异常处理
windows下没有对send()的异常处理,最后一个参数无效,写0就可以了。
linux下
当连接断开,还发数据的时候,不仅send()的返回值会有反映,而且还会像系统发送一个异常消息,如果不作处理,系统会出BrokePipe,程序会退出。为此,send()函数的最后一个参数可以设置MSG_NOSIGNAL,禁止send()函数向系统发送异常消息。
12)WSA宏
windows下WSA相关的操作
linux下WSA相关的操作在Linux不必要,直接去掉即可
3、多线程
多线程:(win)process.h--〉(linux)pthread.h
_beginthread--> pthread_create
_endthread--> pthread_exit
Linux socket的基本操作socket、bind、listen、accept
Linux socket的基本操作涉及到 socket、bind、listen、accept等关键函数。在开始之前,应明确 socket函数的作用类似于普通文件的打开操作,返回一个用于后续读写操作的描述符。创建 socket时,可通过指定参数类型和协议创建不同类型的 socket,但需注意不同类型和协议的组合限制。默认情况下,创建的 socket是主动类型的,后续应通过 bind函数为其绑定特定的地址和端口。bind函数接收地址族、地址和端口作为参数,用于将地址信息赋给 socket。服务器通常在启动时使用 bind函数绑定一个众所周知的地址,以便客户端能连接。而客户端则无需指定地址,系统会自动为其分配端口。在进行 socket操作时,需将主机字节序转换为网络字节序,以确保数据传输的一致性。服务器在调用 listen函数后变为被动监听状态,等待客户端连接请求。客户端调用 connect函数尝试建立连接,服务器通过 accept函数接收请求并建立连接。之后,即可进行网络 I/O操作,类似于普通文件的读写。读写操作可使用 recvmsg()/sendmsg()函数,它们是最通用的 I/O函数,能替代其他 I/O函数。完成操作后,通过 close函数关闭 socket描述符。close操作仅标记 socket为关闭状态,实际关闭需等待引用计数降至零。
linux下的 socket编程问题!
第一个问题:
对,是那样的,用open打开文件,用read读取文件,在发送给对方,接收方接收到后,写入文件就可以了。不过在这个过程中最好别用字符串函数,除非你很熟悉。
第二个问题
首先你得去搞清楚什么是线程,什么是进程,fork出来的叫进程,pthread_create出来的才叫线程。服务器有很多种模型(多进程,多线程,select,epoll模型,这个我的blog上有,famdestiny.cublog.cn),不一定要用多进程。
给你写了个代码,自己先看看:
注意,在自己的目录下创建一个叫pserverb的文件,程序会把这个文件复制成test文件。你可以自己根据需要改改
server:
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<errno.h>
#include<signal.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<string.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#define SERV_PORT 5358
#define MAX_CONN 10
#define BUF_LEN 1024
void str_echo(FILE*fp, int sockfd){
ssize_t nread;
int file_fd;
char buf[BUF_LEN]={0};
file_fd= open("test", O_WRONLY| O_TRUNC| O_CREAT, 0755);
while(1){
bzero(buf, BUF_LEN);
if((nread= read(sockfd, buf, BUF_LEN))==-1){
if(errno== EINTR){
continue;
}
else{
printf("readn error:%s\n", strerror(errno));
continue;
}
}
else if(nread== 0){
break;
}
else{
printf("%s\n", buf);
write(file_fd, buf, nread);
}
}
close(file_fd);
}
void sig_chld(int sig){
pid_t pid;
int state;
while((pid= waitpid(-1,&state, WNOHANG))> 0){
printf("child process%d exited.", pid);
}
return;
}
int main(int argc, char**argv)
{
int listenfd, connfd;
socklen_t cliaddrlen;
pid_t childpid;
struct sockaddr_in servaddr, cliaddr;
if((listenfd= socket(AF_INET, SOCK_STREAM, 0))==-1){
printf("socket error:%s\n", strerror(errno));
return 0;
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family= AF_INET;
servaddr.sin_addr.s_addr= htonl(INADDR_ANY);
servaddr.sin_port= htons(SERV_PORT);
if(bind(listenfd,(struct sockaddr*)&servaddr, sizeof(servaddr))==-1){
printf("bind error:%s\n", strerror(errno));
return 0;
}
if(listen(listenfd, MAX_CONN)==-1){
printf("listen error:%s\n", strerror(errno));
return 0;
}
signal(SIGCHLD, sig_chld);
while(1){
cliaddrlen= sizeof(cliaddr);
if((connfd= accept(listenfd,(struct sockaddr*)&cliaddr,&cliaddrlen))==-1){
if(errno== EINTR){
continue;
}
else{
printf("accept error:%s\n", strerror(errno));
continue;
}
}
if((childpid= fork())== 0){
close(listenfd);
str_echo(stdin, connfd);
exit(0);
}
else if(childpid> 0){
close(connfd);
}
else{
printf("fork error!\n");
continue;
}
}
}
client:
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#define SERV_ADDR"127.0.0.1"
#define SERV_PORT 5358
#define BUF_LEN 1024
void str_cli(char*path, int sockfd)
{
char sendbuf[BUF_LEN]={0};
int fd, n;
if((fd= open("./pserverb", O_RDONLY))==-1){
printf("%s\n", strerror(errno));
exit(0);
}
while((n= read(fd, sendbuf, BUF_LEN))!= 0){
if(n< 0){
printf("%s\n", strerror(errno));
exit(0);
}
write(sockfd, sendbuf, n);
bzero(sendbuf, BUF_LEN);
}
close(fd);
return;
}
int main(int argc, char**argv)
{
int fd;
struct sockaddr_in servaddr;
fd= socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family= AF_INET;
servaddr.sin_addr.s_addr= inet_addr(SERV_ADDR);
servaddr.sin_port= htons(SERV_PORT);
if(connect(fd,(struct sockaddr*)&servaddr, sizeof(servaddr))==-1){
printf("connect error:%s\n", strerror(errno));
return 0;
}
str_cli(argv[1], fd);
return 0;
}